You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
OneAuth/ui/c/table.html

261 lines
7.2 KiB
HTML

<!DOCTYPE html>
<html>
<style>
body {}
.table-column {
flex-grow: 1;
max-width: 30%;
border-bottom: 2px solid black;
background-color: var(--color-background, #fff);
}
.sticky-column {
position: sticky;
z-index: 10;
}
.header-key {
border-bottom: 2px solid black;
padding: 0 0.5rem;
font-size: 1.2rem;
height: 3rem;
line-height: 3rem;
text-overflow: ellipsis;
white-space: nowrap;
display: block;
box-sizing: border-box;
}
.table-value {
display: block;
box-sizing: border-box;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
padding: 0.5rem;
height: 3rem;
line-height: 2rem;
}
.table-value[odd='1'] {
background-color: color-mix(in srgb, var(--color-background, #fff), #888 10%);
}
.table-btn {}
.dialog {
min-height: 50vh;
max-height: 80vh;
overflow: auto;
width: 50vw;
background-color: var(--color-background, #fff);
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
padding: 2rem;
border-radius: 0.5rem;
display: flex;
flex-direction: column;
}
::-webkit-scrollbar,
::-webkit-scrollbar-track {
width: 0.25rem;
height: 0.25rem;
background: none;
border-radius: 5px;
}
::-webkit-scrollbar-thumb {
background: rgba(0, 0, 0, 0.2);
border-radius: 5px;
transform: translateX(10px);
}
.keysearch {
padding: 0.5rem 1rem;
font-size: 0.875rem;
border: 1px solid #d1d5db;
border-radius: 0.375rem;
outline: none;
transition: border-color 0.2s ease-in-out;
}
.keysearch:focus {
border-color: var(--color-primary);
box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.2);
}
</style>
<body>
<div class="flex justify-evenly overflow-x-auto">
<div v-if='!key.hidden' class="table-column" :class="{'sticky-column':index===0}" style="min-height: 21rem;left:0"
v-for='(key,index) in keys'>
<div class="header-key">{{key.label||key.name}}</div>
<div class="table-value" :odd='index%2' v-for='(row, index) in data'>
<vslot :name='key.name' v='row,index' :style="key.style">
<div refu='input' v:value='row[key.name]' :type="key.type==='textarea'?'text':key.type"
:required='key.required' :validate='key.validate' :opts='key.opts'
v-if='editable && !key.disabled && row._enable'>
</div>
<div v-else>
{{ (key.field?key.field(row):row[key.name]) || '&nbsp;'}}
</div>
</vslot>
</div>
</div>
<div class="table-column sticky-column" style="right:0;min-width: 8rem;">
<vslot name='_key' class="header-key">
<div refu='dropdown' class="w-full">
<div refu='icon' class="text-2xl" name='ecs'></div>
<div vslot='menu'>
<div class="dropdown-item" @click='show(0)'>创建</div>
<div class="dropdown-item" @click='show(1)'>高级检索</div>
<div class="dropdown-item" @click='show(2)'>智能导入</div>
</div>
</div>
</vslot>
<div class="table-value" :odd='index%2' v-for='(row, index) in data'>
<vslot class="w-full flex justify-center gap-2 text-xl" name='_addon' v='row,index'>
<div refu='icon' name='edit-square' color='#78c' v-if='!row._enable' @click='row._enable=true'></div>
<div refu='icon' name='save' color='#ff3300' v-else @click='wrap(1, row)'></div>
<div refu='icon' name='delete' color='#f66' v-if='!row._enable' @click='wrap(3, row)'></div>
<div refu='icon' name='close' color='#aaa' v-else @click='delete row._enable'></div>
</vslot>
</div>
</div>
</div>
<div class="flex items-center gap-2 px-4 select-none h-12">
<input !value='listOpts.keyword' @input.delay1s='search' class="keysearch" placeholder="简单检索" />
<div refu='icon' name='left' class="ml-auto" @click='wrap(0,-1)'></div>
<div>{{listOpts.page}}</div>
<div refu='icon' name='right' class="mr-auto" @click='wrap(0,1)'></div>
<div class="">总计{{total}}条数据</div>
</div>
<div refu='dialog' v:show='showFlag'>
<div class="dialog">
<vslot v-if='showMode==0' name='create' v='keys,oncreate'>
<table-create :keys='keys' :oncreate='oncreate'></table-create>
</vslot>
<table-setting :keys='keys' :opts='listOpts' v-else-if='showMode==1' :apply='()=>wrap(0)'>
</table-setting>
<div v-else-if class="w-full flex flex-col flex-grow items-center gap-4" style=" height: calc(100% - 0px);">
<textarea class="w-full bg-gray-200 flex-grow p-4" placeholder="请输入文本内容或者拖入文件" !value='ai_content'
@input='ai_content=$event.target.value' style="resize:vertical;"></textarea>
<div refu='btn' class="mx-auto" size='lg' :click='ai'>智能识别</div>
</div>
</div>
</div>
</body>
<script setup>
showFlag = false
showMode = 0
loading = false
keys = []
data = []
host = window.location.origin
api = ''
editable = false
ai_content = ''
show = (m) => {
showMode = m
showFlag = true
}
function delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
update = async (row) => {
if (api) {
return await $env.api.Patch(host + api + '/' + row.id, row)
}
}
total = 0
listOpts = {
page: 1,
page_size: 10,
keyword: '',
keywords: {},
sort_by: 'created_at',
order: 'desc',
}
next = async (opts) => {
if (api) {
opts = Object.assign({}, opts)
if (opts.keywords && Object.keys(opts.keywords).length > 0) {
opts.keywords = JSON.stringify(opts.keywords)
} else {
delete opts.keywords
}
return await $axios.get(host + api, opts)
}
return []
}
create = async (data) => {
if (api) {
return await $axios.post(host + api, data)
}
return
}
del = async (row) => {
if (api) {
return await $axios.delete(host + api + '/' + row.id, row)
}
}
search = (e) => {
listOpts.keyword = e.target.value
wrap(0)
}
oncreate = async (d) => {
await wrap(2, d)
}
wrap = async (mode, props) => {
try {
if (mode === 0) {
if (typeof props === 'number') {
listOpts.page += props
}
let max = Math.ceil(total / listOpts.page_size)
if (listOpts.page < 1) {
listOpts.page = 1
return
} else if (listOpts.page > max && max > 0) {
listOpts.page = max
return
}
let data = await $data.next(listOpts)
if (Array.isArray(data)) {
$data.data = data
} else {
$data.data = data.items
$data.total = data.total
}
} else if (mode === 1) {
await update(props)
props._enable = false
} else if (mode === 2) {
let res = await create(props)
showFlag = false
$data.data.push(res)
} else if (mode == 3) {
await del(props)
$data.data = $data.data.filter((d) => d.id !== data.id)
}
showFlag = false
} catch (e) {
$data.onerr(e)
}
console.log('done')
}
onerr = (e) => {
console.error(e)
}
</script>
<script>
if ($data.data.length === 0 && $data.api) {
wrap(0)
}
</script>
</html>