feat(mobile-oa-h5): polish form layout and replace inputNumber with decimal field

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zlwuandCursor committed 2026-08-11 13:40:02 +08:00
1 parent a0775cf619
commit b638c787b1
15 files changed
+471 -141

No files matched your search

+5
View File
@@ -5,11 +5,16 @@ import formCreateMobile from '@form-create/vant'
import App from './App.vue'
import router from './router'
import './styles/tokens.css'
import './styles/oa-form.css'
import { registerOaComponents } from './oa/register-components'
import { captureTokenFromUrl } from './utils/auth'
// 三墙主色(勿用 web-admin #10b981)
document.documentElement.style.setProperty('--van-primary-color', '#0a9f6d')
// 须在路由/组件发请求前捕获小程序传入的 ?token=
captureTokenFromUrl()
const app = createApp(App)
app.use(router)
app.use(Vant)
+12 -28
View File
@@ -4,6 +4,7 @@
:model-value="displayText"
readonly
is-link
input-align="left"
:disabled="disabled"
placeholder="请选择部门"
@click="openPicker"
@@ -15,7 +16,13 @@
<strong>选择部门</strong>
<span class="oa-pick__ok" @click="confirm">确定</span>
</div>
<van-search v-model="keyword" placeholder="搜索部门名称" />
<van-search
v-model="keyword"
shape="round"
label-align="left"
input-align="left"
placeholder="搜索部门名称"
/>
<div class="oa-pick__list">
<template v-if="multiple">
<van-checkbox-group v-model="pendingIds">
@@ -26,8 +33,8 @@
:title="d.label"
@click="toggle(d.id)"
>
<template #right-icon>
<van-checkbox :name="d.id" @click.stop />
<template #icon>
<van-checkbox class="oa-pick__check" :name="d.id" @click.stop />
</template>
</van-cell>
</van-checkbox-group>
@@ -41,8 +48,8 @@
:title="d.label"
@click="pendingSingle = d.id"
>
<template #right-icon>
<van-radio :name="d.id" @click.stop />
<template #icon>
<van-radio class="oa-pick__check" :name="d.id" @click.stop />
</template>
</van-cell>
</van-radio-group>
@@ -187,26 +194,3 @@ onMounted(() => {
})
</script>
<style scoped>
.oa-pick__sheet {
display: flex;
flex-direction: column;
height: 100%;
background: #fff;
}
.oa-pick__hd {
display: flex;
align-items: center;
justify-content: space-between;
padding: 14px 16px;
border-bottom: 1px solid var(--border, #dcebe4);
}
.oa-pick__ok {
color: var(--brand-green, #0a9f6d);
font-weight: 600;
}
.oa-pick__list {
flex: 1;
overflow: auto;
}
</style>
@@ -4,6 +4,7 @@
v-model="text"
type="number"
inputmode="decimal"
input-align="left"
:disabled="disabled"
:placeholder="placeholder"
@update:model-value="onInput"
@@ -0,0 +1,63 @@
<template>
<div class="oa-number">
<van-field
v-model="text"
type="number"
inputmode="decimal"
input-align="left"
:disabled="disabled"
:placeholder="placeholder"
@update:model-value="onInput"
/>
</div>
</template>
<script setup>
import { ref, watch } from 'vue'
defineOptions({ name: 'inputNumber' })
const props = defineProps({
modelValue: { type: [Number, String], default: null },
disabled: { type: Boolean, default: false },
placeholder: { type: String, default: '请输入数字' },
formCreateInject: { type: Object, default: null }
})
const emit = defineEmits(['update:modelValue', 'change'])
function toNum(v) {
if (v == null || v === '') return null
const n = typeof v === 'number' ? v : Number(String(v).replace(/,/g, ''))
return Number.isFinite(n) ? n : null
}
const text = ref(props.modelValue == null || props.modelValue === '' ? '' : String(props.modelValue))
watch(
() => props.modelValue,
(v) => {
const next = v == null || v === '' ? '' : String(v)
if (next !== text.value) text.value = next
}
)
function onInput(v) {
// 输入过程保留字符串便于输入小数点;失焦前尽量解析为 number
const raw = v == null ? '' : String(v)
text.value = raw
if (raw === '' || raw === '-' || raw === '.' || raw.endsWith('.')) {
emit('update:modelValue', raw === '' ? null : raw)
emit('change', raw === '' ? null : raw)
return
}
const n = toNum(raw)
emit('update:modelValue', n)
emit('change', n)
}
</script>
<style scoped>
.oa-number {
width: 100%;
}
</style>
@@ -4,6 +4,7 @@
:model-value="displayText"
readonly
is-link
input-align="left"
:disabled="disabled"
placeholder="请选择人员"
@click="openPicker"
@@ -15,7 +16,13 @@
<strong>选择人员</strong>
<span class="oa-pick__ok" @click="confirm">确定</span>
</div>
<van-search v-model="keyword" placeholder="搜索姓名或工号" />
<van-search
v-model="keyword"
shape="round"
label-align="left"
input-align="left"
placeholder="搜索姓名或工号"
/>
<div class="oa-pick__list">
<template v-if="multiple">
<van-checkbox-group v-model="pendingIds">
@@ -27,8 +34,8 @@
:label="u.sub || undefined"
@click="toggle(u.id)"
>
<template #right-icon>
<van-checkbox :name="u.id" @click.stop />
<template #icon>
<van-checkbox class="oa-pick__check" :name="u.id" @click.stop />
</template>
</van-cell>
</van-checkbox-group>
@@ -43,8 +50,8 @@
:label="u.sub || undefined"
@click="pendingSingle = u.id"
>
<template #right-icon>
<van-radio :name="u.id" @click.stop />
<template #icon>
<van-radio class="oa-pick__check" :name="u.id" @click.stop />
</template>
</van-cell>
</van-radio-group>
@@ -150,7 +157,7 @@ function confirm() {
async function loadUsers() {
loading.value = true
try {
const pageSize = 200
const pageSize = 100
const raw = []
let page = 1
for (;;) {
@@ -200,27 +207,3 @@ onMounted(() => {
loadUsers()
})
</script>
<style scoped>
.oa-pick__sheet {
display: flex;
flex-direction: column;
height: 100%;
background: #fff;
}
.oa-pick__hd {
display: flex;
align-items: center;
justify-content: space-between;
padding: 14px 16px;
border-bottom: 1px solid var(--border, #dcebe4);
}
.oa-pick__ok {
color: var(--brand-green, #0a9f6d);
font-weight: 600;
}
.oa-pick__list {
flex: 1;
overflow: auto;
}
</style>
+13 -29
View File
@@ -4,6 +4,7 @@
:model-value="displayText"
readonly
is-link
input-align="left"
:disabled="disabled"
placeholder="请选择职位"
@click="openPicker"
@@ -15,7 +16,13 @@
<strong>选择职位</strong>
<span class="oa-pick__ok" @click="confirm">确定</span>
</div>
<van-search v-model="keyword" placeholder="搜索职位名称或编码" />
<van-search
v-model="keyword"
shape="round"
label-align="left"
input-align="left"
placeholder="搜索职位名称或编码"
/>
<div class="oa-pick__list">
<template v-if="multiple">
<van-checkbox-group v-model="pendingIds">
@@ -27,8 +34,8 @@
:label="p.sub || undefined"
@click="toggle(p.id)"
>
<template #right-icon>
<van-checkbox :name="p.id" @click.stop />
<template #icon>
<van-checkbox class="oa-pick__check" :name="p.id" @click.stop />
</template>
</van-cell>
</van-checkbox-group>
@@ -43,8 +50,8 @@
:label="p.sub || undefined"
@click="pendingSingle = p.id"
>
<template #right-icon>
<van-radio :name="p.id" @click.stop />
<template #icon>
<van-radio class="oa-pick__check" :name="p.id" @click.stop />
</template>
</van-cell>
</van-radio-group>
@@ -150,7 +157,7 @@ function confirm() {
async function loadPosts() {
loading.value = true
try {
const pageSize = 200
const pageSize = 100
const raw = []
let page = 1
for (;;) {
@@ -197,26 +204,3 @@ onMounted(() => {
})
</script>
<style scoped>
.oa-pick__sheet {
display: flex;
flex-direction: column;
height: 100%;
background: #fff;
}
.oa-pick__hd {
display: flex;
align-items: center;
justify-content: space-between;
padding: 14px 16px;
border-bottom: 1px solid var(--border, #dcebe4);
}
.oa-pick__ok {
color: var(--brand-green, #0a9f6d);
font-weight: 600;
}
.oa-pick__list {
flex: 1;
overflow: auto;
}
</style>
@@ -4,6 +4,7 @@
:model-value="summary"
readonly
is-link
input-align="left"
:disabled="disabled"
placeholder="请选择收款账户"
@click="openPicker"
@@ -21,7 +22,13 @@
<strong>选择收款账户</strong>
<span class="oa-recv__ok" @click="confirm">确定</span>
</div>
<van-search v-model="keyword" placeholder="搜索账户名称或账号" />
<van-search
v-model="keyword"
shape="round"
label-align="left"
input-align="left"
placeholder="搜索账户名称或账号"
/>
<div class="oa-recv__list">
<van-checkbox-group v-model="pendingIds">
<van-cell
@@ -31,8 +38,8 @@
:title="a.label"
@click="toggle(a.id)"
>
<template #right-icon>
<van-checkbox :name="a.id" @click.stop />
<template #icon>
<van-checkbox class="oa-recv__check" :name="a.id" @click.stop />
</template>
</van-cell>
</van-checkbox-group>
@@ -146,29 +153,9 @@ onMounted(() => {
color: var(--text-muted, #6b7b74);
font-size: 12px;
line-height: 1.5;
text-align: left;
}
.oa-recv__line + .oa-recv__line {
margin-top: 4px;
}
.oa-recv__sheet {
display: flex;
flex-direction: column;
height: 100%;
background: #fff;
}
.oa-recv__hd {
display: flex;
align-items: center;
justify-content: space-between;
padding: 14px 16px;
border-bottom: 1px solid var(--border, #dcebe4);
}
.oa-recv__ok {
color: var(--brand-green, #0a9f6d);
font-weight: 600;
}
.oa-recv__list {
flex: 1;
overflow: auto;
}
</style>
@@ -61,6 +61,9 @@
</van-tabs>
<van-search
v-model="keyword"
shape="round"
label-align="left"
input-align="left"
placeholder="搜索流程名 / 标题"
@search="loadCandidates"
/>
@@ -74,8 +77,8 @@
:label="pickerLabel(row)"
@click="toggle(row.id)"
>
<template #right-icon>
<van-checkbox :name="row.id" @click.stop />
<template #icon>
<van-checkbox class="oa-rel__check" :name="row.id" @click.stop />
</template>
</van-cell>
</van-checkbox-group>
@@ -266,25 +269,4 @@ watch(
flex: 0 0 auto;
color: #94a3b8;
}
.oa-rel__sheet {
display: flex;
flex-direction: column;
height: 100%;
background: #fff;
}
.oa-rel__hd {
display: flex;
align-items: center;
justify-content: space-between;
padding: 14px 16px;
border-bottom: 1px solid var(--border, #dcebe4);
}
.oa-rel__ok {
color: var(--brand-green, #0a9f6d);
font-weight: 600;
}
.oa-rel__picker {
flex: 1;
overflow: auto;
}
</style>
@@ -3,6 +3,7 @@
<div class="oa-stub__title">{{ title || typeName }}</div>
<van-field
v-model="inner"
input-align="left"
:placeholder="'[' + typeName + '] 占位,后续替换真实交互'"
@update:model-value="onInput"
/>
@@ -16,6 +16,8 @@
<van-field
:model-value="leg.transport"
label="交通工具"
label-align="top"
input-align="left"
readonly
is-link
:disabled="disabled"
@@ -25,6 +27,8 @@
<van-field
:model-value="leg.tripType"
label="单程往返"
label-align="top"
input-align="left"
readonly
is-link
:disabled="disabled"
@@ -34,6 +38,8 @@
<van-field
:model-value="leg.fromCity"
label="出发城市"
label-align="top"
input-align="left"
:disabled="disabled"
placeholder="请输入"
@update:model-value="(v) => patch(idx, { fromCity: v })"
@@ -41,6 +47,8 @@
<van-field
:model-value="leg.toCity"
label="目的城市"
label-align="top"
input-align="left"
:disabled="disabled"
placeholder="请输入"
@update:model-value="(v) => patch(idx, { toCity: v })"
@@ -48,6 +56,8 @@
<van-field
:model-value="leg.startDate"
label="开始日期"
label-align="top"
input-align="left"
readonly
is-link
:disabled="disabled"
@@ -57,6 +67,8 @@
<van-field
:model-value="leg.startHalf"
label="开始时段"
label-align="top"
input-align="left"
readonly
is-link
:disabled="disabled"
@@ -65,6 +77,8 @@
<van-field
:model-value="leg.endDate"
label="结束日期"
label-align="top"
input-align="left"
readonly
is-link
:disabled="disabled"
@@ -74,6 +88,8 @@
<van-field
:model-value="leg.endHalf"
label="结束时段"
label-align="top"
input-align="left"
readonly
is-link
:disabled="disabled"
@@ -82,6 +98,8 @@
<van-field
:model-value="leg.duration == null ? '' : String(leg.duration)"
label="时长(天)"
label-align="top"
input-align="left"
type="number"
:disabled="disabled"
@update:model-value="(v) => patch(idx, { duration: v === '' ? null : Number(v) })"
+10
View File
@@ -0,0 +1,10 @@
/** OA 表单全局 option:标题在上、内容左对齐(覆盖 form-create/vant 默认右对齐) */
export const oaFormOption = {
submitBtn: false,
resetBtn: false,
form: {
labelAlign: 'top',
inputAlign: 'left',
colon: false
}
}
+3 -4
View File
@@ -1,4 +1,5 @@
/** 按 zkxw-sc 已发布模板实际出现的 type 构造;套件带 children(与 Web 结构一致) */
import { oaFormOption } from './form-option.js'
const LEAVE_TYPE_OPTIONS = [
{ label: '事假', value: '事假' },
@@ -39,7 +40,7 @@ export const kitchenSinkRule = [
{ label: '紧急', value: 'urgent' }
]
},
{ type: 'inputNumber', field: 'qty', title: '数字', value: 1 },
{ type: 'inputNumber', field: 'qty', title: '数字', value: 1, props: { placeholder: '请输入数字,可含小数' } },
{
type: 'datePicker',
field: 'bizDate',
@@ -277,7 +278,5 @@ export const kitchenSinkRule = [
]
export const kitchenSinkOption = {
submitBtn: false,
resetBtn: false,
form: { labelPosition: 'top' }
...oaFormOption
}
@@ -1,4 +1,5 @@
import OaMoneyField from './components/OaMoneyField.vue'
import OaNumberField from './components/OaNumberField.vue'
import OaUploadField from './components/OaUploadField.vue'
import OaReceiveAccountSelect from './components/OaReceiveAccountSelect.vue'
import OaRelatedApproval from './components/OaRelatedApproval.vue'
@@ -12,6 +13,7 @@ import OaTripItinerary from './components/OaTripItinerary.vue'
/** 与 web-admin type 名对齐 */
const REAL_COMPONENTS = {
inputNumber: OaNumberField,
money: OaMoneyField,
upload: OaUploadField,
receiveAccount: OaReceiveAccountSelect,
+275
View File
@@ -0,0 +1,275 @@
/* form-create + Vant:上下布局与左对齐兜底 */
.form-create-m .van-field__label--top {
width: 100%;
margin-bottom: 6px;
text-align: left;
color: var(--text-primary, #1f2a26);
font-size: 13px;
font-weight: 600;
}
.form-create-m .van-field__control {
text-align: left !important;
}
.form-create-m .van-field__control::placeholder {
text-align: left;
color: var(--text-muted, #6b7b74);
}
.form-create-m .fc-form-item {
margin-bottom: 4px;
}
/* 自定义控件 / 内置选择触发条:占满整行,箭头贴右 */
.form-create-m ._fc-select,
.form-create-m ._fc-date-picker,
.form-create-m ._fc-time-picker,
.form-create-m ._fc-calendar,
.form-create-m ._fc-cascader,
.form-create-m .oa-pick,
.form-create-m .oa-money,
.form-create-m .oa-number,
.form-create-m .oa-recv,
.form-create-m .oa-rel,
.form-create-m .oa-trip,
.form-create-m .oa-upload {
display: block;
width: 100%;
box-sizing: border-box;
}
/*
* 内层触发 Field 会继承 Form 的 labelAlign=top,导致 value 占满一行、箭头折到下一行最左。
* 这里强制单行横排:value 撑满,right-icon 固定右侧。
*/
.form-create-m ._fc-select > .van-cell,
.form-create-m ._fc-date-picker > .van-cell,
.form-create-m ._fc-time-picker > .van-cell,
.form-create-m ._fc-calendar > .van-cell,
.form-create-m ._fc-cascader > .van-cell,
.form-create-m .oa-pick > .van-cell,
.form-create-m .oa-money > .van-cell,
.form-create-m .oa-number > .van-cell,
.form-create-m .oa-recv > .van-cell {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: center;
width: 100%;
box-sizing: border-box;
}
.form-create-m ._fc-select > .van-cell > .van-cell__title,
.form-create-m ._fc-date-picker > .van-cell > .van-cell__title,
.form-create-m ._fc-time-picker > .van-cell > .van-cell__title,
.form-create-m ._fc-calendar > .van-cell > .van-cell__title,
.form-create-m ._fc-cascader > .van-cell > .van-cell__title,
.form-create-m .oa-pick > .van-cell > .van-cell__title,
.form-create-m .oa-recv > .van-cell > .van-cell__title {
display: none;
}
.form-create-m ._fc-select > .van-cell > .van-cell__value,
.form-create-m ._fc-date-picker > .van-cell > .van-cell__value,
.form-create-m ._fc-time-picker > .van-cell > .van-cell__value,
.form-create-m ._fc-calendar > .van-cell > .van-cell__value,
.form-create-m ._fc-cascader > .van-cell > .van-cell__value,
.form-create-m .oa-pick > .van-cell > .van-cell__value,
.form-create-m .oa-money > .van-cell > .van-cell__value,
.form-create-m .oa-number > .van-cell > .van-cell__value,
.form-create-m .oa-recv > .van-cell > .van-cell__value {
flex: 1 1 auto;
width: auto !important;
max-width: none !important;
min-width: 0;
text-align: left;
}
.form-create-m ._fc-select > .van-cell > .van-cell__right-icon,
.form-create-m ._fc-date-picker > .van-cell > .van-cell__right-icon,
.form-create-m ._fc-time-picker > .van-cell > .van-cell__right-icon,
.form-create-m ._fc-calendar > .van-cell > .van-cell__right-icon,
.form-create-m ._fc-cascader > .van-cell > .van-cell__right-icon,
.form-create-m .oa-pick > .van-cell > .van-cell__right-icon,
.form-create-m .oa-recv > .van-cell > .van-cell__right-icon {
flex: 0 0 auto;
margin-left: 8px;
order: 3;
}
/* 行程内带自身 label 的 Field:标题在上,箭头仍在内容行右侧 */
.form-create-m .oa-trip .van-field--label-top {
display: flex;
flex-wrap: wrap;
align-items: center;
width: 100%;
}
.form-create-m .oa-trip .van-field--label-top > .van-cell__title {
flex: 0 0 100%;
width: 100%;
}
.form-create-m .oa-trip .van-field--label-top > .van-cell__value {
flex: 1 1 auto;
min-width: 0;
text-align: left;
}
.form-create-m .oa-trip .van-field--label-top > .van-cell__right-icon {
flex: 0 0 auto;
margin-left: 8px;
}
/* 外层表单项:标题独占一行;内容区整行左对齐(箭头在内层控件右侧) */
.form-create-m .fc-form-item.van-field--label-top {
flex-wrap: wrap;
}
.form-create-m .fc-form-item.van-field--label-top > .van-cell__title {
flex: 0 0 100%;
width: 100%;
margin-bottom: 6px;
}
.form-create-m .fc-form-item.van-field--label-top > .van-cell__value {
flex: 1 1 100%;
width: 100%;
max-width: 100%;
}
/* 选择弹窗通用 */
.oa-pick__sheet,
.oa-recv__sheet,
.oa-rel__sheet {
display: flex;
flex-direction: column;
height: 100%;
background: #fff;
}
.oa-pick__hd,
.oa-recv__hd,
.oa-rel__hd {
display: flex;
align-items: center;
justify-content: space-between;
padding: 14px 16px;
border-bottom: 1px solid var(--border, #dcebe4);
}
.oa-pick__hd strong,
.oa-recv__hd strong,
.oa-rel__hd strong {
font-size: 16px;
font-weight: 700;
color: var(--text-primary, #1f2a26);
}
.oa-pick__hd > span:first-child,
.oa-recv__hd > span:first-child,
.oa-rel__hd > span:first-child {
min-width: 48px;
color: var(--text-muted, #6b7b74);
font-size: 14px;
}
.oa-pick__ok,
.oa-recv__ok,
.oa-rel__ok {
min-width: 48px;
color: var(--brand-green, #0a9f6d);
font-size: 14px;
font-weight: 600;
text-align: right;
}
.oa-pick__list,
.oa-recv__list,
.oa-rel__picker {
flex: 1;
padding: 12px;
overflow: auto;
background: transparent;
box-sizing: border-box;
}
.oa-pick__list .van-cell,
.oa-recv__list .van-cell,
.oa-rel__picker .van-cell {
align-items: center;
margin-bottom: 10px;
padding: 12px 14px;
text-align: left;
background: transparent;
border-radius: 10px;
}
.oa-pick__list .van-cell:last-child,
.oa-recv__list .van-cell:last-child,
.oa-rel__picker .van-cell:last-child {
margin-bottom: 0;
}
.oa-pick__list .van-cell::after,
.oa-recv__list .van-cell::after,
.oa-rel__picker .van-cell::after {
display: none;
}
.oa-pick__list .van-cell__title,
.oa-recv__list .van-cell__title,
.oa-rel__picker .van-cell__title {
text-align: left;
}
.oa-pick__list .van-cell__label,
.oa-recv__list .van-cell__label,
.oa-rel__picker .van-cell__label {
text-align: left;
color: var(--text-muted, #6b7b74);
}
.oa-pick__check,
.oa-recv__check,
.oa-rel__check {
margin-right: 8px;
}
/* 弹窗检索:勿继承表单 labelAlign=top,保持单行垂直居中 */
.oa-pick__sheet .van-search,
.oa-recv__sheet .van-search,
.oa-rel__sheet .van-search {
padding: 10px 12px;
background: #fff;
}
.oa-pick__sheet .van-search .van-search__content,
.oa-recv__sheet .van-search .van-search__content,
.oa-rel__sheet .van-search .van-search__content {
align-items: center;
}
.oa-pick__sheet .van-search .van-cell,
.oa-recv__sheet .van-search .van-cell,
.oa-rel__sheet .van-search .van-cell {
align-items: center;
padding-top: 0;
padding-bottom: 0;
min-height: 36px;
}
.oa-pick__sheet .van-search .van-field__body,
.oa-recv__sheet .van-search .van-field__body,
.oa-rel__sheet .van-search .van-field__body {
align-items: center;
}
.oa-pick__sheet .van-search .van-field__control,
.oa-recv__sheet .van-search .van-field__control,
.oa-rel__sheet .van-search .van-field__control {
height: 36px;
line-height: 36px;
text-align: left !important;
}
+39 -3
View File
@@ -1,9 +1,45 @@
/** 从 URL ?token= 读取登录态(小程序 web-view 传入) */
export function getToken() {
/** 小程序 web-view 通过 URL ?token= 传入登录态;落盘避免路由跳转后丢失 */
const TOKEN_KEY = 'zkxw_oa_h5_token'
function readQueryToken() {
try {
const q = new URLSearchParams(window.location.search)
const q = new URLSearchParams(window.location.search || '')
return String(q.get('token') || '').trim()
} catch {
return ''
}
}
/** 启动时调用:把 URL 中的 token 写入 sessionStorage,并尽量从地址栏摘掉敏感参数 */
export function captureTokenFromUrl() {
const fromQuery = readQueryToken()
if (fromQuery) {
try {
sessionStorage.setItem(TOKEN_KEY, fromQuery)
} catch {
/* ignore quota / private mode */
}
try {
const url = new URL(window.location.href)
if (url.searchParams.has('token')) {
url.searchParams.delete('token')
const next = `${url.pathname}${url.search}${url.hash}`
window.history.replaceState(window.history.state, '', next)
}
} catch {
/* ignore */
}
return fromQuery
}
return getToken()
}
export function getToken() {
try {
const cached = String(sessionStorage.getItem(TOKEN_KEY) || '').trim()
if (cached) return cached
} catch {
/* ignore */
}
return readQueryToken()
}