BUG修复,及部分页面增加按钮权限

This commit is contained in:
Songsl 2026-04-28 22:29:59 +08:00
parent 2f54ebef78
commit 6a714a77a9
14 changed files with 323 additions and 195 deletions

View File

@ -1,58 +1,65 @@
<template> <template>
<el-dialog :model-value="visible" :title="title" :width="width" :destroy-on-close="destroyOnClose" <el-dialog
:fullscreen="fullscreen" :model-value="visible"
@close="handleClose" v-bind="$attrs"> :title="title"
<!-- 对话框内容插槽 --> :width="width"
<slot /> align-center
:destroy-on-close="destroyOnClose"
:fullscreen="fullscreen"
@close="handleClose"
v-bind="$attrs"
>
<!-- 对话框内容插槽 -->
<slot />
<!-- 底部按钮插槽 --> <!-- 底部按钮插槽 -->
<template #footer v-if="showFooter"> <template #footer v-if="showFooter">
<slot name="footer"> <slot name="footer">
<el-button @click="handleCancel">取消</el-button> <el-button @click="handleCancel">取消</el-button>
<el-button type="primary" @click="handleConfirm">确定</el-button> <el-button type="primary" @click="handleConfirm">确定</el-button>
</slot> </slot>
</template> </template>
</el-dialog> </el-dialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
interface Props { interface Props {
visible: boolean visible: boolean
title: string title: string
width?: string | number width?: string | number
destroyOnClose?: boolean destroyOnClose?: boolean
type?: string type?: string
showFooter?: boolean showFooter?: boolean
fullscreen?: boolean fullscreen?: boolean
} }
interface Emits { interface Emits {
(e: 'update:visible', value: boolean): void (e: 'update:visible', value: boolean): void
(e: 'confirm'): void (e: 'confirm'): void
(e: 'cancel'): void (e: 'cancel'): void
(e: 'close'): void (e: 'close'): void
} }
const props = withDefaults(defineProps<Props>(), { const props = withDefaults(defineProps<Props>(), {
width: '750px', width: '750px',
destroyOnClose: true, destroyOnClose: true,
showFooter: true, showFooter: true,
fullscreen: false, fullscreen: false,
}) })
const emit = defineEmits<Emits>() const emit = defineEmits<Emits>()
const handleConfirm = () => { const handleConfirm = () => {
emit('confirm') emit('confirm')
} }
const handleCancel = () => { const handleCancel = () => {
emit('update:visible', false) emit('update:visible', false)
emit('cancel') emit('cancel')
} }
const handleClose = () => { const handleClose = () => {
emit('close') emit('close')
} }
</script> </script>

View File

@ -1,102 +1,130 @@
<template> <template>
<div class="search-container"> <div class="search-container">
<el-form :model="searchForm" inline @submit.prevent> <el-form :model="searchForm" inline @submit.prevent>
<!-- 动态生成的表单项 --> <!-- 动态生成的表单项 -->
<template v-for="item in searchOptions" :key="item.prop"> <template v-for="item in searchOptions" :key="item.prop">
<el-form-item :label="item.label" :prop="item.prop" v-if="!item.slot" <el-form-item
:style="{ minWidth: item.minWidth, width: item.width }"> v-auth="item.auth || ''"
<!-- 输入框 --> :label="item.label"
<el-input v-if="item.type === 'input'" v-model="searchForm[item.prop]" :prop="item.prop"
:placeholder="item.placeholder || `请输入${item.label}`" :clearable="item.clearable ?? true" v-if="!item.slot"
:disabled="item.disabled" @blur="handleBlur"/> :style="{
minWidth: item.minWidth,
width: item.width,
flex: item.width ? '0 0 auto' : '',
}"
>
<!-- 输入框 -->
<el-input
v-if="item.type === 'input'"
v-model="searchForm[item.prop]"
:placeholder="item.placeholder || `请输入${item.label}`"
:clearable="item.clearable ?? true"
:disabled="item.disabled"
@blur="handleBlur"
/>
<!-- 选择器 --> <!-- 选择器 -->
<el-select v-else-if="item.type === 'select'" v-model="searchForm[item.prop]" <el-select
:placeholder="item.placeholder || `请选择${item.label}`" :clearable="item.clearable ?? true" v-else-if="item.type === 'select'"
:disabled="item.disabled"> v-model="searchForm[item.prop]"
<el-option v-for="option in item.options" :key="option.value" :label="option.label" :placeholder="item.placeholder || `请选择${item.label}`"
:value="option.value" /> :clearable="item.clearable ?? true"
</el-select> :disabled="item.disabled"
>
<el-option
v-for="option in item.options"
:key="option.value"
:label="option.label"
:value="option.value"
/>
</el-select>
<!-- 日期选择器单个/范围 --> <!-- 日期选择器单个/范围 -->
<el-date-picker v-else-if="item.type === 'date'" v-model="searchForm[item.prop]" <el-date-picker
:type="item.dateType || 'date'" :range-separator="item.rangeSeparator || '至'" v-else-if="item.type === 'date'"
:start-placeholder="item.startPlaceholder || '开始日期'" v-model="searchForm[item.prop]"
:end-placeholder="item.endPlaceholder || '结束日期'" :type="item.dateType || 'date'"
:value-format="item.valueFormat || 'YYYY-MM-DD'" :clearable="item.clearable ?? true" :range-separator="item.rangeSeparator || '至'"
:disabled-date="item.disabledDate" :locale="'zhCn'" /> :start-placeholder="item.startPlaceholder || '开始日期'"
</el-form-item> :end-placeholder="item.endPlaceholder || '结束日期'"
:value-format="item.valueFormat || 'YYYY-MM-DD'"
:clearable="item.clearable ?? true"
:disabled-date="item.disabledDate"
:locale="'zhCn'"
/>
</el-form-item>
<!-- 自定义插槽项 --> <!-- 自定义插槽项 -->
<el-form-item :label="item.label" :prop="item.prop" v-else> <el-form-item :label="item.label" :prop="item.prop" v-else>
<slot :name="item.prop" :form="searchForm" /> <slot :name="item.prop" :form="searchForm" />
</el-form-item> </el-form-item>
</template> </template>
<!-- 额外插槽用于插入配置外的自定义项 --> <!-- 额外插槽用于插入配置外的自定义项 -->
<slot name="extra" :form="searchForm" /> <slot name="extra" :form="searchForm" />
<!-- 操作按钮 --> <!-- 操作按钮 -->
<el-form-item> <el-form-item>
<el-button type="primary" @click="$emit('search')"> <el-button type="primary" @click="$emit('search')">
{{ buttonConfig.searchText || '搜索' }} {{ buttonConfig.searchText || '搜索' }}
</el-button> </el-button>
<el-button @click="$emit('reset')"> <el-button @click="$emit('reset')">
{{ buttonConfig.resetText || '重置' }} {{ buttonConfig.resetText || '重置' }}
</el-button> </el-button>
<!-- 按钮区插槽 --> <!-- 按钮区插槽 -->
<slot name="button" :form="searchForm" /> <slot name="button" :form="searchForm" />
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
// //
interface SearchOption { interface SearchOption {
prop: string; // prop: string //
label: string; // label: string //
type: 'input' | 'select' | 'date'; // type: 'input' | 'select' | 'date' //
slot?: boolean; // slot?: boolean //
placeholder?: string; // placeholder?: string //
clearable?: boolean; // clearable?: boolean //
disabled?: boolean; // disabled?: boolean //
options?: { label: string; value: any }[]; // // options?: { label: string; value: any }[] // //
dateType?: 'date' | 'daterange' | 'datetime' | 'datetimerange'; // dateType?: 'date' | 'daterange' | 'datetime' | 'datetimerange' //
rangeSeparator?: string; // rangeSeparator?: string //
startPlaceholder?: string; // startPlaceholder?: string //
endPlaceholder?: string; // endPlaceholder?: string //
valueFormat?: string; // valueFormat?: string //
disabledDate?: (date: Date) => boolean; // disabledDate?: (date: Date) => boolean //
width?: string; // width?: string //
minWidth?: string; // minWidth?: string //
auth?: string //
} }
// //
interface ButtonConfig { interface ButtonConfig {
searchText?: string; searchText?: string
resetText?: string; resetText?: string
} }
// Props // Props
const props = defineProps({ const props = defineProps({
searchForm: { searchForm: {
type: Object, type: Object,
required: true, required: true,
}, },
searchOptions: { searchOptions: {
type: Array as () => SearchOption[ type: Array as () => SearchOption[],
], required: true,
required: true, },
}, buttonConfig: {
buttonConfig: { type: Object as () => ButtonConfig,
type: Object as () => ButtonConfig, default: () => ({}),
default: () => ({}), },
}
}) })
// //
const emit = defineEmits(['search', 'reset','blur-input']) const emit = defineEmits(['search', 'reset', 'blur-input'])
// 3. 👇 // 3. 👇
const handleBlur = () => { const handleBlur = () => {
emit('blur-input') emit('blur-input')
@ -105,24 +133,24 @@ const handleBlur = () => {
<style scoped lang="scss"> <style scoped lang="scss">
.search-container { .search-container {
margin-bottom: 20px; margin-bottom: 20px;
.el-form { .el-form {
display: flex; display: flex;
width: 100%; width: 100%;
.el-form-item { .el-form-item {
flex: 1 1 auto; flex: 1 1 auto;
}
} }
}
:deep(.el-form-item) { :deep(.el-form-item) {
margin-bottom: 0; margin-bottom: 0;
margin-right: 16px; margin-right: 16px;
} }
:deep(.el-button) { :deep(.el-button) {
margin-left: 8px; margin-left: 8px;
} }
} }
</style> </style>

View File

@ -1,17 +1,29 @@
import type { Directive, DirectiveBinding } from 'vue' import type { Directive, DirectiveBinding } from 'vue'
import {getStorage} from '@/utils/storage' import { getStorage } from '@/utils/storage'
/** /**
* v-auth - * v-auth -
* v-auth="'admin'" v-auth="'user:read,user:write'" * v-auth="'admin'" v-auth="'user:read,user:write'"
*/ */
export const authDirective: Directive = { export const authDirective: Directive = {
mounted(el: HTMLElement, binding: DirectiveBinding) { mounted(el: HTMLElement, binding: DirectiveBinding) {
checkPermission(el, binding.value, true) checkPermission(el, binding.value, 'some')
}, },
updated(el: HTMLElement, binding: DirectiveBinding) { updated(el: HTMLElement, binding: DirectiveBinding) {
checkPermission(el, binding.value, true) checkPermission(el, binding.value, 'some')
},
}
/**
* v-auth-all -
* v-auth-all="'user:read,user:write'"
*/
export const authAllDirective: Directive = {
mounted(el: HTMLElement, binding: DirectiveBinding) {
checkPermission(el, binding.value, 'every')
},
updated(el: HTMLElement, binding: DirectiveBinding) {
checkPermission(el, binding.value, 'every')
}, },
} }
@ -21,10 +33,10 @@ export const authDirective: Directive = {
*/ */
export const authNotDirective: Directive = { export const authNotDirective: Directive = {
mounted(el: HTMLElement, binding: DirectiveBinding) { mounted(el: HTMLElement, binding: DirectiveBinding) {
checkPermission(el, binding.value, false) checkPermission(el, binding.value, 'none')
}, },
updated(el: HTMLElement, binding: DirectiveBinding) { updated(el: HTMLElement, binding: DirectiveBinding) {
checkPermission(el, binding.value, false) checkPermission(el, binding.value, 'none')
}, },
} }
@ -32,28 +44,64 @@ export const authNotDirective: Directive = {
* *
* @param el DOM * @param el DOM
* @param value * @param value
* @param shouldContain true=false= * @param mode 'some'=, 'every'=, 'none'=
*/ */
function checkPermission(el: HTMLElement, value: string | string[], shouldContain: boolean) { function checkPermission(
if (!value) { el: HTMLElement,
shouldContain ? el.remove() : (el.style.display = '') value: string | string[],
mode: 'some' | 'every' | 'none',
) {
// 空字符串/空数组时some/every 模式展示none 模式隐藏
if (!value || (Array.isArray(value) && value.length === 0)) {
if (mode === 'none') {
el.remove()
} else {
el.style.display = ''
}
return return
} }
// 统一处理为字符串并分割 // 统一处理为字符串数组
const permissions = Array.isArray(value) ? value : value.split(',').map((p) => p.trim()) const permissions = Array.isArray(value)
? value.map((p) => String(p).trim()).filter(Boolean)
: String(value)
.split(',')
.map((p) => p.trim())
.filter(Boolean)
// 如果过滤后为空(比如传入 ",," 这种情况),同空值处理
if (permissions.length === 0) {
if (mode === 'none') {
el.remove()
} else {
el.style.display = ''
}
return
}
// 白名单权限配置(可从后端获取或配置文件读取) // 白名单权限配置(可从后端获取或配置文件读取)
const WHITE_LIST = getStorage('btnAuth'); const WHITE_LIST: string[] = getStorage('btnAuth') || []
// 检查是否有任一权限在白名单中 let hasPermission: boolean
const hasPermission = permissions.some((p) => WHITE_LIST.includes(p))
// 根据 shouldContain 决定显示/隐藏 switch (mode) {
if (shouldContain) { case 'some':
hasPermission ? (el.style.display = '') : el.remove() // 任一权限满足即显示
} else { hasPermission = permissions.some((p) => WHITE_LIST.includes(p))
hasPermission ? el.remove() : (el.style.display = '') hasPermission ? (el.style.display = '') : el.remove()
break
case 'every':
// 全部权限满足才显示
hasPermission = permissions.every((p) => WHITE_LIST.includes(p))
hasPermission ? (el.style.display = '') : el.remove()
break
case 'none':
// 不包含任一权限时显示
hasPermission = permissions.some((p) => WHITE_LIST.includes(p))
hasPermission ? el.remove() : (el.style.display = '')
break
} }
} }
@ -62,5 +110,6 @@ function checkPermission(el: HTMLElement, value: string | string[], shouldContai
*/ */
export function setupAuthDirective(app: any) { export function setupAuthDirective(app: any) {
app.directive('auth', authDirective) app.directive('auth', authDirective)
app.directive('auth-all', authAllDirective)
app.directive('auth-not', authNotDirective) app.directive('auth-not', authNotDirective)
} }

View File

@ -15,14 +15,14 @@
:highlight-current-row="false" :highlight-current-row="false"
> >
<!-- 操作列插槽 --> <!-- 操作列插槽 -->
<template #operation="{ row }"> <!-- <template #operation="{ row }">-->
<el-button type="primary" :disabled="row.status !== '1'" @click="handleAudit(row, 3)" <!-- <el-button type="primary" :disabled="row.status !== '1'" @click="handleAudit(row, 3)"-->
>审核通过</el-button <!-- >审核通过</el-button-->
> <!-- >-->
<el-button type="danger" :disabled="row.status !== '1'" @click="handleAudit(row, 4)" <!-- <el-button type="danger" :disabled="row.status !== '1'" @click="handleAudit(row, 4)"-->
>审核驳回</el-button <!-- >审核驳回</el-button-->
> <!-- >-->
</template> <!-- </template>-->
</OrderRechangeTable> </OrderRechangeTable>
<!-- 分页区域使用接口返回的 total / current_page / per_page --> <!-- 分页区域使用接口返回的 total / current_page / per_page -->

View File

@ -55,6 +55,6 @@ export const tableColumns = [
{ prop: 'statusText', label: '状态', align: 'center' as const }, { prop: 'statusText', label: '状态', align: 'center' as const },
{ prop: 'rechangeTime', label: '充值时间', align: 'center' as const }, { prop: 'rechangeTime', label: '充值时间', align: 'center' as const },
{ prop: 'rechangeAccount', label: '充值账号', align: 'center' as const }, { prop: 'rechangeAccount', label: '充值账号', align: 'center' as const },
{ label: '操作', width: '240px', align: 'center' as const, slotName: 'operation' }, // { label: '操作', width: '240px', align: 'center' as const, slotName: 'operation' },
] ]

View File

@ -236,6 +236,7 @@ const getCustomerList = async () => {
const data: any = await getAgentListApi(params) const data: any = await getAgentListApi(params)
tableTree.value = data.data.map((item: any) => ({ tableTree.value = data.data.map((item: any) => ({
...item,
accountName: item.username, accountName: item.username,
userId: item.id, userId: item.id,
status: item.status === 1 ? '正常' : '禁用', status: item.status === 1 ? '正常' : '禁用',

View File

@ -5,7 +5,7 @@ export const search = [
label: '账号名称', label: '账号名称',
type: 'input' as const, type: 'input' as const,
placeholder: '请输入账号名称', placeholder: '请输入账号名称',
width: '150px', width: '200px',
}, },
// 开始时间 // 开始时间
{ {
@ -14,6 +14,7 @@ export const search = [
type: 'date' as const, type: 'date' as const,
dateType: 'date' as const, // 时间范围选择器 dateType: 'date' as const, // 时间范围选择器
valueFormat: 'YYYY-MM-DD', valueFormat: 'YYYY-MM-DD',
width: '240px',
}, },
// 结束时间 // 结束时间
{ {
@ -22,28 +23,30 @@ export const search = [
type: 'date' as const, type: 'date' as const,
dateType: 'date' as const, // 时间范围选择器 dateType: 'date' as const, // 时间范围选择器
valueFormat: 'YYYY-MM-DD', valueFormat: 'YYYY-MM-DD',
width: '240px',
}, },
] ]
export const tableColumns = [ export const tableColumns = [
// 账号名称 // 账号名称
{ label: '账号名称', prop: 'accountName'}, { label: '账号名称', prop: 'accountName' },
// 账号id // 账号id
{ prop: 'userId', label: '账号id' }, { prop: 'userId', label: '账号id' },
// 状态 // 状态
{ prop: 'status', label: '状态' }, { prop: 'status', label: '状态' },
// 账号角色 // 账号角色
{ prop: 'role', label: '账号角色' }, { prop: 'role', label: '账号角色' },
// 账号数量 // 账号数量
{ prop: 'accountQty', label: '账号数量' }, { prop: 'accountQty', label: '账号数量' },
// 点差分配比例 { prop: 'wallet_capital.amount', label: '资金', align: 'center' as const },
{ prop: 'marginRatio', label: '点差分配比例', slotName: 'marginRatio' }, // 点差分配比例
// 手续费分成比例 { prop: 'marginRatio', label: '点差分配比例', slotName: 'marginRatio' },
{ prop: 'commissionRatio', label: '手续费分成比例', slotName: 'commissionRatio' }, // 手续费分成比例
// 注册时间 { prop: 'commissionRatio', label: '手续费分成比例', slotName: 'commissionRatio' },
{ prop: 'createTime', label: '注册时间', sortable: true }, // 注册时间
// 操作 { prop: 'createTime', label: '注册时间', sortable: true },
// { label: '操作', slotName: 'action' } // 操作
// { label: '操作', slotName: 'action' }
] ]
// 点差表格配置 // 点差表格配置

View File

@ -8,7 +8,7 @@
@reset="handleReset" @reset="handleReset"
> >
<template #button="{ form }"> <template #button="{ form }">
<el-button type="primary" @click="handleAddMarket()" v-auth="'agent_createAgen'"> <el-button type="primary" @click="handleAddMarket()" v-auth="'agent_createAgent'">
添加 添加
</el-button> </el-button>
<el-button <el-button

View File

@ -50,12 +50,13 @@ export const clientSearch = [
//定义客户table列配置 //定义客户table列配置
export const clientTableColumns = [ export const clientTableColumns = [
{ prop: 'id', label: 'ID', align: 'center' as const }, { prop: 'id', label: 'ID', align: 'center' as const },
{ prop: 'username', label: '用户名', align: 'center' as const }, { prop: 'username', label: '用户名', align: 'center' as const },
{ prop: 'createdTime', label: '注册时间', align: 'center' as const }, { prop: 'createdTime', label: '注册时间', align: 'center' as const },
{ prop: 'agentUsername', label: '所属代理', align: 'center' as const }, { prop: 'agentUsername', label: '所属代理', align: 'center' as const },
{ label: '状态', slotName: 'status', align: 'center' as const }, { prop: 'wallet_capital.amount', label: '资金', align: 'center' as const },
{ label: '操作', slotName: 'action', align: 'center' as const } { label: '状态', slotName: 'status', align: 'center' as const },
{ label: '操作', slotName: 'action', align: 'center' as const },
] ]
//定义添加客户form配置 //定义添加客户form配置

View File

@ -107,7 +107,7 @@ const menuFormRef = ref<FormInstance>()
const menuFormRules = rules(menuForm.value, menuiconOptions) const menuFormRules = rules(menuForm.value, menuiconOptions)
// icon // icon
const menuFormOptionsMap = ref({ const menuFormOptionsMap = ref({
parentName: [] as any[], parent_id: [] as any[],
icon: menuiconOptions, icon: menuiconOptions,
type: [ type: [
{ label: '菜单', value: 1 }, { label: '菜单', value: 1 },
@ -142,7 +142,7 @@ const fetchMenuList = async () => {
label: item.name, label: item.name,
value: item.id ?? '', value: item.id ?? '',
})) }))
menuFormOptionsMap.value.parentName = [{ label: '一级菜单', value: '0' }, ...parentNameOptions] menuFormOptionsMap.value.parent_id = [{ label: '一级菜单', value: '0' }, ...parentNameOptions]
} catch (err) { } catch (err) {
console.error('获取菜单列表失败', err) console.error('获取菜单列表失败', err)
} }
@ -187,7 +187,7 @@ const handleSubmit = async () => {
if (dialogType.value === 'add') { if (dialogType.value === 'add') {
const params = { const params = {
name: menuForm.value.name, // name: menuForm.value.name, //
parent_id: menuForm.value.parentName, // id parent_id: menuForm.value.parent_id, // id
path: menuForm.value.path, // path: menuForm.value.path, //
api: menuForm.value.api, // api: menuForm.value.api, //
icon: menuForm.value.icon, // icon: menuForm.value.icon, //
@ -213,6 +213,7 @@ const handleCancel = () => {
menuForm.value = { menuForm.value = {
name: '', // name: '', //
parentName: '', // parentName: '', //
parent_id: '', //
path: '', // path: '', //
api: '', // api: '', //
icon: '', // icon: '', //
@ -227,6 +228,7 @@ const handleClose = () => {
menuForm.value = { menuForm.value = {
name: '', // name: '', //
parentName: '', // parentName: '', //
parent_id: '', //
path: '', // path: '', //
api: '', // api: '', //
icon: '', // icon: '', //

View File

@ -37,12 +37,17 @@ export const menuTableColumns = [
//定义menuForm配置 //定义menuForm配置
export const menuFormItemOptions = [ export const menuFormItemOptions = [
{ prop: 'name', label: '菜单名称', type: 'input' as const,placeholder: '请输入菜单名称' }, { prop: 'name', label: '菜单名称', type: 'input' as const, placeholder: '请输入菜单名称' },
{ prop: 'parentName', label: '父级菜单', type: 'select' as const, placeholder: '请选择父级菜单' }, { prop: 'parent_id', label: '父级菜单', type: 'select' as const, placeholder: '请选择父级菜单' },
{ prop: 'path', label: '前端路由', type: 'input' as const, placeholder: '请输入前端路由路径' }, { prop: 'path', label: '前端路由', type: 'input' as const, placeholder: '请输入前端路由路径' },
{ prop: 'api', label: '后端路由', type: 'input' as const, placeholder: '请输入后端路由' }, { prop: 'api', label: '后端路由', type: 'input' as const, placeholder: '请输入后端路由' },
{ prop: 'icon', label: '图标名称', type: 'select' as const, placeholder: '请选择图标名称' }, { prop: 'icon', label: '图标名称', type: 'select' as const, placeholder: '请选择图标名称' },
{ prop: 'sort', label: '排序', type: 'number' as const, placeholder: '请输入排序,数字越小越靠前' }, {
{ prop: 'type', label: '菜单类型', type: 'radio' as const, placeholder: '请选择菜单类型' }, prop: 'sort',
{ prop: 'status', label: '状态', type: 'radio' as const, placeholder: '请选择状态' }, label: '排序',
type: 'number' as const,
placeholder: '请输入排序,数字越小越靠前',
},
{ prop: 'type', label: '菜单类型', type: 'radio' as const, placeholder: '请选择菜单类型' },
{ prop: 'status', label: '状态', type: 'radio' as const, placeholder: '请选择状态' },
] ]

View File

@ -7,7 +7,7 @@ export const search = [
label: '公告名称', label: '公告名称',
type: 'input' as const, type: 'input' as const,
placeholder: '请输入公告名称', placeholder: '请输入公告名称',
width: '120px', width: '220px',
}, },
{ {
prop: 'startDateTime', prop: 'startDateTime',
@ -15,7 +15,7 @@ export const search = [
type: 'date' as const, type: 'date' as const,
dateType: 'date' as const, // 时间范围选择器 dateType: 'date' as const, // 时间范围选择器
valueFormat: 'YYYY-MM-DD', valueFormat: 'YYYY-MM-DD',
width: '180px', width: '220px',
}, },
{ {
prop: 'endDateTime', prop: 'endDateTime',
@ -23,7 +23,7 @@ export const search = [
type: 'date' as const, type: 'date' as const,
dateType: 'date' as const, // 时间范围选择器 dateType: 'date' as const, // 时间范围选择器
valueFormat: 'YYYY-MM-DD', valueFormat: 'YYYY-MM-DD',
width: '180px', width: '220px',
}, },
{ {
prop: 'status', prop: 'status',
@ -34,6 +34,7 @@ export const search = [
{ label: '草稿', value: 1 }, { label: '草稿', value: 1 },
{ label: '已发布', value: 2 }, { label: '已发布', value: 2 },
], ],
width: '220px',
}, },
] ]

View File

@ -12,7 +12,7 @@
type="primary" type="primary"
:disabled="!selectedRow" :disabled="!selectedRow"
@click="handleEdit()" @click="handleEdit()"
v-auth="'contracVarietediariety'" v-auth="'contractVariety_editVariety'"
> >
编辑 编辑
</el-button> </el-button>
@ -57,11 +57,13 @@
> >
<template #upload="{ formData }"> <template #upload="{ formData }">
<el-upload <el-upload
ref="uploadRef"
v-model:file-list="fileList" v-model:file-list="fileList"
class="upload-demo" class="upload-demo"
:http-request="handleUpload" :http-request="handleUpload"
:before-upload="beforeUpload" :before-upload="beforeUpload"
:limit="1" :limit="1"
:on-exceed="handleExceed"
> >
<el-button type="primary">点击上传</el-button> <el-button type="primary">点击上传</el-button>
<template #tip> <template #tip>
@ -287,6 +289,19 @@ const handleReset = () => {
const handleEdit = () => { const handleEdit = () => {
getTradeGroupList() getTradeGroupList()
const row = selectedRow.value const row = selectedRow.value
if (row.image) {
fileList.value = [
{
name: row.image.split('/').pop() || 'existing.jpg',
url: row.image,
status: 'success',
},
]
} else {
fileList.value = []
}
varietyForm.value = { varietyForm.value = {
...row, ...row,
id: row.id, id: row.id,
@ -367,6 +382,21 @@ const handleUpload = async (options: any) => {
} }
} }
const uploadRef = ref()
const handleExceed = (files: File[]) => {
//
if (uploadRef.value) {
uploadRef.value.clearFiles()
}
//
const file = files[0]
if (file) {
uploadRef.value?.handleStart(file) //
// http-request
handleUpload({ file, onSuccess: () => {}, onError: () => {} })
}
}
// + 20KB = 20 * 1024 // + 20KB = 20 * 1024
const beforeUpload = (file: File) => { const beforeUpload = (file: File) => {
// //
@ -446,6 +476,7 @@ const handleCancel = () => {
dialogVisible.value = false dialogVisible.value = false
} }
const handleClose = () => { const handleClose = () => {
fileList.value = []
dialogVisible.value = false dialogVisible.value = false
} }

View File

@ -84,7 +84,7 @@ const handleInput = (index: number, val: string) => {
const handleFocus = (index: number) => { const handleFocus = (index: number) => {
// //
inputList[index] = ''; // inputList[index] = '';
} }
// //