af-mobile-client-vue3 1.2.27 → 1.2.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +184 -0
- package/package.json +1 -1
- package/src/components/data/XCellList/index.vue +9 -1
- package/src/components/data/XFormGroup/index.vue +31 -22
- package/src/components/data/XReportForm/DateTimeSecondsPicker.vue +208 -0
- package/src/components/data/XReportForm/index.vue +86 -116
- package/src/styles/app.less +5 -0
- package/src/views/component/XFormGroupView/index.vue +38 -1
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
This is a Vue 3 mobile client application (`af-mobile-client-vue3`) built as a smart gas system (智慧燃气) mobile application. It serves as a micro-frontend main application with comprehensive business components and dynamic form capabilities.
|
|
8
|
+
|
|
9
|
+
## Development Commands
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Install dependencies
|
|
13
|
+
pnpm install
|
|
14
|
+
|
|
15
|
+
# Development server (with mock server on port 8086)
|
|
16
|
+
pnpm dev
|
|
17
|
+
|
|
18
|
+
# Build for production
|
|
19
|
+
pnpm build
|
|
20
|
+
|
|
21
|
+
# Build for development environment
|
|
22
|
+
pnpm build:dev
|
|
23
|
+
|
|
24
|
+
# Lint and type checking
|
|
25
|
+
pnpm lint
|
|
26
|
+
|
|
27
|
+
# Auto-fix linting issues
|
|
28
|
+
pnpm lint:fix
|
|
29
|
+
|
|
30
|
+
# Type checking only
|
|
31
|
+
pnpm typecheck
|
|
32
|
+
|
|
33
|
+
# Version release
|
|
34
|
+
pnpm release
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Technology Stack
|
|
38
|
+
|
|
39
|
+
- **Vue 3** with Composition API and `<script setup>` syntax
|
|
40
|
+
- **TypeScript** for type safety
|
|
41
|
+
- **Vite** as build tool (port 7190)
|
|
42
|
+
- **Vant 4** as primary UI component library
|
|
43
|
+
- **Pinia** for state management with persistence
|
|
44
|
+
- **pnpm** as package manager (requires Node.js >=20.19.0)
|
|
45
|
+
- **UnoCSS** for atomic CSS utilities
|
|
46
|
+
- **@micro-zoe/micro-app** for micro-frontend architecture
|
|
47
|
+
|
|
48
|
+
## Code Style & Standards
|
|
49
|
+
|
|
50
|
+
From `.cursorrules`:
|
|
51
|
+
|
|
52
|
+
- Use Composition API and `<script setup>` syntax
|
|
53
|
+
- Component names: PascalCase (e.g., `UserProfile`)
|
|
54
|
+
- Variables: camelCase (e.g., `userName`)
|
|
55
|
+
- Boolean variables: use `is/has/should` prefix (e.g., `isLoading`)
|
|
56
|
+
- Event handlers: use `handle` prefix (e.g., `handleSubmit`)
|
|
57
|
+
- CSS classes: kebab-case (e.g., `user-profile`)
|
|
58
|
+
- **Must explicitly import Vant components** - auto-import is disabled for this component library project
|
|
59
|
+
- Use `interface` for type definitions, `type` for unions/intersections
|
|
60
|
+
- Props must specify types
|
|
61
|
+
|
|
62
|
+
## Architecture
|
|
63
|
+
|
|
64
|
+
### Directory Structure
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
src/
|
|
68
|
+
├── components/
|
|
69
|
+
│ ├── core/ # Core UI components (NavBar, Tabbar, Uploader)
|
|
70
|
+
│ ├── data/ # Business data components
|
|
71
|
+
│ │ ├── XReportForm/ # Dynamic form with JSON configuration
|
|
72
|
+
│ │ ├── XReportGrid/ # Data grid with reporting
|
|
73
|
+
│ │ ├── XForm/ # General form components
|
|
74
|
+
│ │ └── XOlMap/ # OpenLayers map integration
|
|
75
|
+
│ └── layout/ # Layout components
|
|
76
|
+
├── stores/ # Pinia state management
|
|
77
|
+
├── utils/ # Utility functions
|
|
78
|
+
├── views/ # Page components
|
|
79
|
+
├── router/ # Vue Router configuration
|
|
80
|
+
└── api/ # API layer
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Key Business Components
|
|
84
|
+
|
|
85
|
+
**XReportForm Component** (`src/components/data/XReportForm/index.vue`):
|
|
86
|
+
|
|
87
|
+
- Dynamic form generation from JSON configuration
|
|
88
|
+
- Supports field types: `input`, `datePicker`, `timePicker`, `dateTimeSecondsPicker`, `curDateInput`, `signature`, `images`, `inputs`, `inputColumns`
|
|
89
|
+
- Built-in validation with custom error messages
|
|
90
|
+
- Slot-based extensibility for complex layouts
|
|
91
|
+
- Integration with file upload and signature capture
|
|
92
|
+
|
|
93
|
+
**XReportGrid Component**:
|
|
94
|
+
|
|
95
|
+
- Data grid with reporting capabilities
|
|
96
|
+
- Print functionality integration
|
|
97
|
+
- Design mode for form configuration
|
|
98
|
+
|
|
99
|
+
**XOlMap Component**:
|
|
100
|
+
|
|
101
|
+
- OpenLayers integration for GIS functionality
|
|
102
|
+
- Location picker with coordinate transformation
|
|
103
|
+
|
|
104
|
+
### State Management
|
|
105
|
+
|
|
106
|
+
- **Pinia stores** with persistence via `pinia-plugin-persistedstate`
|
|
107
|
+
- **User store**: Authentication, permissions, user data
|
|
108
|
+
- **Settings store**: Application configuration
|
|
109
|
+
- **Route cache store**: Performance optimization
|
|
110
|
+
|
|
111
|
+
### API Layer
|
|
112
|
+
|
|
113
|
+
- **Axios-based HTTP client** with interceptors
|
|
114
|
+
- **Request/Response transformers** for v3/v4 API compatibility
|
|
115
|
+
- **Automatic token management** and error handling
|
|
116
|
+
- **Mock server integration** for development
|
|
117
|
+
|
|
118
|
+
## Development Workflow
|
|
119
|
+
|
|
120
|
+
### Server Configuration
|
|
121
|
+
|
|
122
|
+
- Development server runs on port 7190
|
|
123
|
+
- Mock server runs on port 8086
|
|
124
|
+
- Multiple API proxy endpoints configured in `vite.config.ts`
|
|
125
|
+
|
|
126
|
+
### Build Process
|
|
127
|
+
|
|
128
|
+
- Code splitting: `third` (node_modules), `views` (business pages)
|
|
129
|
+
- Assets organized in `static/` directory with hashing
|
|
130
|
+
- CSS code splitting disabled for mobile optimization
|
|
131
|
+
- Legacy browser support via `@vitejs/plugin-legacy`
|
|
132
|
+
|
|
133
|
+
### Git Hooks
|
|
134
|
+
|
|
135
|
+
- Pre-commit: `pnpm lint-staged` (ESLint auto-fix)
|
|
136
|
+
- Commit message: `pnpm commitlint` (conventional commits)
|
|
137
|
+
|
|
138
|
+
## Micro-Frontend Integration
|
|
139
|
+
|
|
140
|
+
This is a main application for micro-frontend architecture:
|
|
141
|
+
|
|
142
|
+
- Uses `@micro-zoe/micro-app` for micro-app management
|
|
143
|
+
- Child apps register in `microApps.ts`
|
|
144
|
+
- Supports dynamic loading and routing
|
|
145
|
+
- Unmount function available at `window.unmount`
|
|
146
|
+
|
|
147
|
+
## Mobile-Specific Features
|
|
148
|
+
|
|
149
|
+
- **@vant/touch-emulator** for desktop development
|
|
150
|
+
- **postcss-mobile-forever** for viewport handling
|
|
151
|
+
- **vite-plugin-pwa** for PWA capabilities
|
|
152
|
+
- **VConsole** for mobile debugging
|
|
153
|
+
- Dark mode support throughout the application
|
|
154
|
+
|
|
155
|
+
## Common Patterns
|
|
156
|
+
|
|
157
|
+
### Adding New Field Types to XReportForm
|
|
158
|
+
|
|
159
|
+
1. Add type to `generateDefaultRequiredMessage()` function
|
|
160
|
+
2. Add case in `formatConfigToForm()` switch statement
|
|
161
|
+
3. Add template section in the component template
|
|
162
|
+
4. Follow existing patterns for validation and data binding
|
|
163
|
+
|
|
164
|
+
### Component Development
|
|
165
|
+
|
|
166
|
+
- Use `<script setup lang="ts">` syntax
|
|
167
|
+
- Explicitly import Vant components
|
|
168
|
+
- Define props with TypeScript interfaces
|
|
169
|
+
- Use `defineEmits` for events
|
|
170
|
+
- Follow existing component structure patterns
|
|
171
|
+
|
|
172
|
+
### API Integration
|
|
173
|
+
|
|
174
|
+
- Use the existing HTTP client in `src/utils/http/`
|
|
175
|
+
- Follow v3/v4 API patterns established in the codebase
|
|
176
|
+
- Handle errors consistently with existing patterns
|
|
177
|
+
|
|
178
|
+
## Testing & Quality
|
|
179
|
+
|
|
180
|
+
- **ESLint** with `@antfu/eslint-config`
|
|
181
|
+
- **TypeScript** strict mode
|
|
182
|
+
- **Vue TSC** for type checking
|
|
183
|
+
- **Commitlint** for commit message standards
|
|
184
|
+
- **Lint-staged** for pre-commit hooks
|
package/package.json
CHANGED
|
@@ -146,6 +146,14 @@ const slots = useSlots()
|
|
|
146
146
|
// 当前组件实例(不推荐使用,可能会在后续的版本更迭中调整,暂时用来绑定函数的上下文)
|
|
147
147
|
const currInst = getCurrentInstance()
|
|
148
148
|
|
|
149
|
+
// 列表底部的文字显示
|
|
150
|
+
function finishedBottomText() {
|
|
151
|
+
if (buttonState.value?.add && buttonState.value.add === true && (filterButtonPermissions('add').state === false || ((filterButtonPermissions('add').state === true && userState.f.resources.f_role_name.includes((filterButtonPermissions('add').roleStr))))))
|
|
152
|
+
return '已加载全部内容,如需新增请点击右上角的 + 号'
|
|
153
|
+
else
|
|
154
|
+
return '已加载全部内容'
|
|
155
|
+
}
|
|
156
|
+
|
|
149
157
|
onBeforeMount(() => {
|
|
150
158
|
initComponent()
|
|
151
159
|
})
|
|
@@ -584,7 +592,7 @@ defineExpose({
|
|
|
584
592
|
v-model:loading="loading"
|
|
585
593
|
class="list_main"
|
|
586
594
|
:finished="finished"
|
|
587
|
-
finished-text="
|
|
595
|
+
:finished-text="finishedBottomText()"
|
|
588
596
|
:immediate-check="isInitQuery"
|
|
589
597
|
@load="onLoad"
|
|
590
598
|
>
|
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import XForm from '@af-mobile-client-vue3/components/data/XForm/index.vue'
|
|
3
3
|
import { getConfigByName } from '@af-mobile-client-vue3/services/api/common'
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
Tab as VanTab,
|
|
7
|
-
Tabs as VanTabs,
|
|
8
|
-
} from 'vant'
|
|
9
|
-
import { defineEmits, defineProps, onBeforeMount, ref, watch } from 'vue'
|
|
4
|
+
import { Button as VanButton, Tab as VanTab, Tabs as VanTabs } from 'vant'
|
|
5
|
+
import { defineEmits, defineProps, onBeforeMount, onMounted, ref, watch } from 'vue'
|
|
10
6
|
|
|
11
7
|
const props = withDefaults(defineProps<{
|
|
12
8
|
configName?: string
|
|
@@ -34,16 +30,12 @@ const submitGroup = ref(false)
|
|
|
34
30
|
const submitSimple = ref(false)
|
|
35
31
|
const isInit = ref(false)
|
|
36
32
|
const initStatus = ref(false)
|
|
37
|
-
const propsData = ref({})
|
|
33
|
+
const propsData = ref<Form>({})
|
|
38
34
|
|
|
39
35
|
// 组件初始化函数
|
|
40
36
|
function init(params: Form) {
|
|
41
37
|
initStatus.value = true
|
|
42
38
|
propsData.value = {
|
|
43
|
-
// configName: '',
|
|
44
|
-
// serviceName: undefined,
|
|
45
|
-
// groupFormData: () => ({}),
|
|
46
|
-
// mode: '查询',
|
|
47
39
|
configName: props.configName,
|
|
48
40
|
serviceName: props.serviceName,
|
|
49
41
|
groupFormData: props.groupFormData,
|
|
@@ -53,7 +45,6 @@ function init(params: Form) {
|
|
|
53
45
|
formData.value = propsData.value.groupFormData
|
|
54
46
|
getConfigByName(propsData.value.configName, (result) => {
|
|
55
47
|
if (result?.groups) {
|
|
56
|
-
// submitGroup.value = true
|
|
57
48
|
groupItems.value = result.groups
|
|
58
49
|
result.groups.forEach((group) => {
|
|
59
50
|
if (!formData.value[group.groupName])
|
|
@@ -63,7 +54,7 @@ function init(params: Form) {
|
|
|
63
54
|
})
|
|
64
55
|
}
|
|
65
56
|
else {
|
|
66
|
-
submitSimple.value = result
|
|
57
|
+
submitSimple.value = result?.showSubmitBtn
|
|
67
58
|
groupItems.value = [{ ...result }]
|
|
68
59
|
}
|
|
69
60
|
isInit.value = true
|
|
@@ -85,24 +76,29 @@ async function submit() {
|
|
|
85
76
|
emit('submit', formData.value)
|
|
86
77
|
}
|
|
87
78
|
|
|
88
|
-
//
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
79
|
+
// 动态计算 offsetTop = var(--van-nav-bar-height) + 10px
|
|
80
|
+
const offsetTop = ref(0)
|
|
81
|
+
onMounted(() => {
|
|
82
|
+
const root = document.documentElement
|
|
83
|
+
const navBarHeight = getComputedStyle(root).getPropertyValue('--van-nav-bar-height')
|
|
84
|
+
offsetTop.value = Number.parseInt(navBarHeight, 10) || 60 + 10
|
|
85
|
+
})
|
|
92
86
|
|
|
93
87
|
defineExpose({ init })
|
|
94
88
|
</script>
|
|
95
89
|
|
|
96
90
|
<template>
|
|
97
91
|
<div v-if="isInit" id="x-form-group">
|
|
98
|
-
<VanTabs scrollspy sticky>
|
|
92
|
+
<VanTabs scrollspy sticky :offset-top="offsetTop">
|
|
99
93
|
<VanTab
|
|
100
94
|
v-for="(item, index) in groupItems"
|
|
101
95
|
:key="item.groupName ? (item.groupName + index) : index"
|
|
102
96
|
:title="item.describe ? item.describe : item.tableName "
|
|
103
97
|
>
|
|
104
|
-
<div
|
|
105
|
-
|
|
98
|
+
<div
|
|
99
|
+
class="x-form-group-item"
|
|
100
|
+
:class="{ 'is-last': index === groupItems.length - 1 }"
|
|
101
|
+
>
|
|
106
102
|
<XForm
|
|
107
103
|
ref="xFormListRef"
|
|
108
104
|
:is-group-form="true"
|
|
@@ -125,10 +121,23 @@ defineExpose({ init })
|
|
|
125
121
|
|
|
126
122
|
<style scoped lang="less">
|
|
127
123
|
#x-form-group {
|
|
124
|
+
display: flex;
|
|
125
|
+
flex-direction: column;
|
|
128
126
|
background-color: rgb(247, 248, 250);
|
|
129
|
-
|
|
127
|
+
height: calc(100vh - var(--van-nav-bar-height) - 20px);
|
|
128
|
+
flex: 1;
|
|
129
|
+
overflow-y: auto;
|
|
130
|
+
// 让 Tabs 区域自适应剩余空间
|
|
131
|
+
.van-tabs {
|
|
132
|
+
flex: 1;
|
|
133
|
+
min-height: 0;
|
|
134
|
+
overflow: auto;
|
|
135
|
+
}
|
|
130
136
|
.x-form-group-item {
|
|
131
|
-
margin: 20px
|
|
137
|
+
margin-bottom: 20px;
|
|
132
138
|
}
|
|
133
139
|
}
|
|
140
|
+
.x-form-group-item.is-last {
|
|
141
|
+
min-height: calc(100vh - var(--van-nav-bar-height) - 40px);
|
|
142
|
+
}
|
|
134
143
|
</style>
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { Field as vanField, Picker as vanPicker, Popup as vanPopup } from 'vant'
|
|
3
|
+
import { computed, ref, watch } from 'vue'
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
modelValue?: string | number | Date
|
|
7
|
+
label?: string
|
|
8
|
+
placeholder?: string
|
|
9
|
+
title?: string
|
|
10
|
+
format?: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
14
|
+
modelValue: undefined,
|
|
15
|
+
label: '选择时间',
|
|
16
|
+
placeholder: '请选择时间',
|
|
17
|
+
title: '选择完整时间',
|
|
18
|
+
format: 'YYYY-MM-DD HH:mm:ss',
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const emit = defineEmits<{
|
|
22
|
+
'update:modelValue': [value: string]
|
|
23
|
+
'confirm': [value: string]
|
|
24
|
+
}>()
|
|
25
|
+
|
|
26
|
+
const showPicker = ref(false)
|
|
27
|
+
const columns = ref<any[]>([])
|
|
28
|
+
const selectedValues = ref<string[]>([])
|
|
29
|
+
|
|
30
|
+
const displayValue = computed(() => {
|
|
31
|
+
if (props.modelValue) {
|
|
32
|
+
const date = new Date(props.modelValue)
|
|
33
|
+
return formatDate(date, props.format)
|
|
34
|
+
}
|
|
35
|
+
return ''
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
watch(() => showPicker.value, (val) => {
|
|
39
|
+
if (val) {
|
|
40
|
+
columns.value = []
|
|
41
|
+
selectedValues.value = []
|
|
42
|
+
getColumns()
|
|
43
|
+
}
|
|
44
|
+
}, { immediate: true })
|
|
45
|
+
|
|
46
|
+
function formatDate(date: Date, format: string): string {
|
|
47
|
+
const year = date.getFullYear()
|
|
48
|
+
const month = String(date.getMonth() + 1).padStart(2, '0')
|
|
49
|
+
const day = String(date.getDate()).padStart(2, '0')
|
|
50
|
+
const hours = String(date.getHours()).padStart(2, '0')
|
|
51
|
+
const minutes = String(date.getMinutes()).padStart(2, '0')
|
|
52
|
+
const seconds = String(date.getSeconds()).padStart(2, '0')
|
|
53
|
+
|
|
54
|
+
return format
|
|
55
|
+
.replace('YYYY', String(year))
|
|
56
|
+
.replace('YY', String(year).slice(-2))
|
|
57
|
+
.replace('MM', month)
|
|
58
|
+
.replace('DD', day)
|
|
59
|
+
.replace('HH', hours)
|
|
60
|
+
.replace('mm', minutes)
|
|
61
|
+
.replace('ss', seconds)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function getColumns() {
|
|
65
|
+
const strtime = props.modelValue ? String(props.modelValue) : ''
|
|
66
|
+
|
|
67
|
+
let dateValues: Date
|
|
68
|
+
if (strtime) {
|
|
69
|
+
const date = new Date(strtime.replace(/-/g, '/'))
|
|
70
|
+
dateValues = date
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
dateValues = new Date()
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const Y = dateValues.getFullYear()
|
|
77
|
+
const M = dateValues.getMonth()
|
|
78
|
+
const D = dateValues.getDate()
|
|
79
|
+
const h = dateValues.getHours()
|
|
80
|
+
const m = dateValues.getMinutes()
|
|
81
|
+
const s = dateValues.getSeconds()
|
|
82
|
+
|
|
83
|
+
// 生成年份列 (前后10年)
|
|
84
|
+
const year: any[] = []
|
|
85
|
+
const currentYear = new Date().getFullYear()
|
|
86
|
+
for (let i = currentYear - 10; i < currentYear + 10; i++) {
|
|
87
|
+
year.push({ text: i.toString(), value: i.toString() })
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// 生成月份列 (01-12)
|
|
91
|
+
const month: any[] = []
|
|
92
|
+
for (let i = 1; i <= 12; i++) {
|
|
93
|
+
const monthStr = i.toString().padStart(2, '0')
|
|
94
|
+
month.push({ text: monthStr, value: monthStr })
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// 生成日期列 (01-31,根据当前年月动态计算)
|
|
98
|
+
const daysInMonth = getCountDays(Y, M + 1)
|
|
99
|
+
const day: any[] = []
|
|
100
|
+
for (let i = 1; i <= daysInMonth; i++) {
|
|
101
|
+
const dayStr = i.toString().padStart(2, '0')
|
|
102
|
+
day.push({ text: dayStr, value: dayStr })
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// 生成小时列 (00-23)
|
|
106
|
+
const hour: any[] = []
|
|
107
|
+
for (let i = 0; i < 24; i++) {
|
|
108
|
+
const hourStr = i.toString().padStart(2, '0')
|
|
109
|
+
hour.push({ text: hourStr, value: hourStr })
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// 生成分钟列 (00-59)
|
|
113
|
+
const minute: any[] = []
|
|
114
|
+
for (let i = 0; i < 60; i++) {
|
|
115
|
+
const minuteStr = i.toString().padStart(2, '0')
|
|
116
|
+
minute.push({ text: minuteStr, value: minuteStr })
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// 生成秒钟列 (00-59)
|
|
120
|
+
const second: any[] = []
|
|
121
|
+
for (let i = 0; i < 60; i++) {
|
|
122
|
+
const secondStr = i.toString().padStart(2, '0')
|
|
123
|
+
second.push({ text: secondStr, value: secondStr })
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
columns.value = [year, month, day, hour, minute, second]
|
|
127
|
+
|
|
128
|
+
// 设置默认选中值
|
|
129
|
+
const _M = (M + 1).toString().padStart(2, '0')
|
|
130
|
+
const _D = D.toString().padStart(2, '0')
|
|
131
|
+
const _h = h.toString().padStart(2, '0')
|
|
132
|
+
const _m = m.toString().padStart(2, '0')
|
|
133
|
+
const _s = s.toString().padStart(2, '0')
|
|
134
|
+
|
|
135
|
+
selectedValues.value = [Y.toString(), _M, _D, _h, _m, _s]
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function getCountDays(year: number, month: number): number {
|
|
139
|
+
const day = new Date(year, month, 0)
|
|
140
|
+
return day.getDate()
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function onChange() {
|
|
144
|
+
// 当年月发生变化时,重新计算日期列
|
|
145
|
+
if (selectedValues.value.length >= 2) {
|
|
146
|
+
const year = Number.parseInt(selectedValues.value[0])
|
|
147
|
+
const month = Number.parseInt(selectedValues.value[1])
|
|
148
|
+
const currentDay = Number.parseInt(selectedValues.value[2])
|
|
149
|
+
|
|
150
|
+
const daysInMonth = getCountDays(year, month)
|
|
151
|
+
|
|
152
|
+
// 重新生成日期列
|
|
153
|
+
const dayColumn: any[] = []
|
|
154
|
+
for (let i = 1; i <= daysInMonth; i++) {
|
|
155
|
+
const dayStr = i.toString().padStart(2, '0')
|
|
156
|
+
dayColumn.push({ text: dayStr, value: dayStr })
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// 如果当前选中的日期超过了新月份的最大天数,调整为最大天数
|
|
160
|
+
if (currentDay > daysInMonth) {
|
|
161
|
+
selectedValues.value[2] = daysInMonth.toString().padStart(2, '0')
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// 更新列
|
|
165
|
+
columns.value[2] = dayColumn
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function onCancel() {
|
|
170
|
+
showPicker.value = false
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function onConfirm() {
|
|
174
|
+
const endval = `${selectedValues.value[0]}-${selectedValues.value[1]}-${selectedValues.value[2]} ${selectedValues.value[3]}:${selectedValues.value[4]}:${selectedValues.value[5]}`
|
|
175
|
+
|
|
176
|
+
emit('update:modelValue', endval)
|
|
177
|
+
emit('confirm', endval)
|
|
178
|
+
showPicker.value = false
|
|
179
|
+
}
|
|
180
|
+
</script>
|
|
181
|
+
|
|
182
|
+
<template>
|
|
183
|
+
<div>
|
|
184
|
+
<van-field
|
|
185
|
+
v-model="displayValue"
|
|
186
|
+
:label="label"
|
|
187
|
+
:placeholder="placeholder"
|
|
188
|
+
readonly
|
|
189
|
+
is-link
|
|
190
|
+
@click="showPicker = true"
|
|
191
|
+
/>
|
|
192
|
+
|
|
193
|
+
<van-popup v-model:show="showPicker" position="bottom" round @close="onCancel">
|
|
194
|
+
<van-picker
|
|
195
|
+
v-model="selectedValues"
|
|
196
|
+
:title="title"
|
|
197
|
+
:columns="columns"
|
|
198
|
+
@change="onChange"
|
|
199
|
+
@cancel="onCancel"
|
|
200
|
+
@confirm="onConfirm"
|
|
201
|
+
/>
|
|
202
|
+
</van-popup>
|
|
203
|
+
</div>
|
|
204
|
+
</template>
|
|
205
|
+
|
|
206
|
+
<style scoped>
|
|
207
|
+
/* 可以根据需要添加自定义样式 */
|
|
208
|
+
</style>
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import Uploader from '@af-mobile-client-vue3/components/core/Uploader/index.vue'
|
|
3
|
+
import DateTimeSecondsPicker from '@af-mobile-client-vue3/components/data/XReportForm/DateTimeSecondsPicker.vue'
|
|
3
4
|
import XReportFormJsonRender from '@af-mobile-client-vue3/components/data/XReportForm/XReportFormJsonRender.vue'
|
|
4
5
|
import XSignature from '@af-mobile-client-vue3/components/data/XSignature/index.vue'
|
|
5
6
|
import { getConfigByNameWithoutIndexedDB } from '@af-mobile-client-vue3/services/api/common'
|
|
6
7
|
import {
|
|
7
8
|
showFailToast,
|
|
8
|
-
Toast,
|
|
9
9
|
Button as vanButton,
|
|
10
10
|
Cell as vanCell,
|
|
11
11
|
CellGroup as vanCellGroup,
|
|
@@ -17,9 +17,7 @@ import {
|
|
|
17
17
|
Skeleton as vanSkeleton,
|
|
18
18
|
} from 'vant'
|
|
19
19
|
import { defineEmits, nextTick, reactive, ref, watch } from 'vue'
|
|
20
|
-
//
|
|
21
|
-
import VueHashCalendar from 'vue3-hash-calendar'
|
|
22
|
-
import 'vue3-hash-calendar/es/index.css'
|
|
20
|
+
// 移除 VueHashCalendar,使用自定义的 DateTimeSecondsPicker
|
|
23
21
|
|
|
24
22
|
// ------------------------- 类型定义 -------------------------
|
|
25
23
|
interface configDefine {
|
|
@@ -66,12 +64,6 @@ let timer: NodeJS.Timeout
|
|
|
66
64
|
const scanFinish = ref(false)
|
|
67
65
|
// 折叠面板当前激活的值
|
|
68
66
|
const activeCollapseName = ref('副标题')
|
|
69
|
-
// 日期选择器显示状态
|
|
70
|
-
const showDatePicker = ref(false)
|
|
71
|
-
const showTimePicker = ref(false)
|
|
72
|
-
// 当前操作的日期时间字段
|
|
73
|
-
const currentDateField = ref('')
|
|
74
|
-
const currentTimeField = ref('')
|
|
75
67
|
|
|
76
68
|
watch(() => props.configName, () => {
|
|
77
69
|
// 这里是你的处理逻辑
|
|
@@ -128,6 +120,8 @@ function generateDefaultRequiredMessage(field: any): string {
|
|
|
128
120
|
return `请选择${label || '日期'}`
|
|
129
121
|
case 'timePicker':
|
|
130
122
|
return `请选择${label || '时间'}`
|
|
123
|
+
case 'dateTimeSecondsPicker':
|
|
124
|
+
return `请选择${label || '完整时间'}`
|
|
131
125
|
case 'curDateInput':
|
|
132
126
|
return `请设置${label || '时间'}`
|
|
133
127
|
case 'signature':
|
|
@@ -564,6 +558,12 @@ function formatConfigToForm(config: configDefine): void {
|
|
|
564
558
|
tempObj.type = 'timePicker'
|
|
565
559
|
tempObj.required = row[j].required
|
|
566
560
|
break
|
|
561
|
+
case 'dateTimeSecondsPicker' :
|
|
562
|
+
tempObj.dataIndex = row[j].dataIndex
|
|
563
|
+
tempObj.text = row[j].text
|
|
564
|
+
tempObj.type = 'dateTimeSecondsPicker'
|
|
565
|
+
tempObj.required = row[j].required
|
|
566
|
+
break
|
|
567
567
|
case 'signature' :
|
|
568
568
|
tempObj.dataIndex = row[j].dataIndex
|
|
569
569
|
tempObj.text = row[j].text
|
|
@@ -855,45 +855,7 @@ function getNow() {
|
|
|
855
855
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
|
|
856
856
|
}
|
|
857
857
|
|
|
858
|
-
//
|
|
859
|
-
function openDatePicker(dataIndex: string) {
|
|
860
|
-
console.log('打开日期选择器:', dataIndex)
|
|
861
|
-
currentDateField.value = dataIndex
|
|
862
|
-
showDatePicker.value = true
|
|
863
|
-
console.log('日期选择器状态:', showDatePicker.value)
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
// 打开时间选择器
|
|
867
|
-
function openTimePicker(dataIndex: string) {
|
|
868
|
-
console.log('打开时间选择器:', dataIndex)
|
|
869
|
-
currentTimeField.value = dataIndex
|
|
870
|
-
showTimePicker.value = true
|
|
871
|
-
console.log('时间选择器状态:', showTimePicker.value)
|
|
872
|
-
}
|
|
873
|
-
|
|
874
|
-
// 确认选择日期
|
|
875
|
-
function onConfirmDate(value: any) {
|
|
876
|
-
console.log('onConfirmDate', value)
|
|
877
|
-
activatedConfig.data[currentDateField.value] = value
|
|
878
|
-
showDatePicker.value = false
|
|
879
|
-
currentDateField.value = ''
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
// 确认选择时间
|
|
883
|
-
function onConfirmTime(value: any) {
|
|
884
|
-
console.log('onConfirmTime', value)
|
|
885
|
-
activatedConfig.data[currentTimeField.value] = value
|
|
886
|
-
showTimePicker.value = false
|
|
887
|
-
currentTimeField.value = ''
|
|
888
|
-
}
|
|
889
|
-
|
|
890
|
-
// 取消选择
|
|
891
|
-
function onCancelPicker() {
|
|
892
|
-
showDatePicker.value = false
|
|
893
|
-
showTimePicker.value = false
|
|
894
|
-
currentDateField.value = ''
|
|
895
|
-
currentTimeField.value = ''
|
|
896
|
-
}
|
|
858
|
+
// 移除了旧的日期时间选择器相关方法,现在使用 DateTimeSecondsPicker 组件
|
|
897
859
|
</script>
|
|
898
860
|
|
|
899
861
|
<template>
|
|
@@ -913,46 +875,46 @@ function onCancelPicker() {
|
|
|
913
875
|
<!-- 标题 -->
|
|
914
876
|
<h2 v-if="activatedConfig.title" class="title" v-html="activatedConfig.title" />
|
|
915
877
|
<!-- 副标题 -->
|
|
916
|
-
<div v-if="activatedConfig.subTitle && activatedConfig.subTitle.length > 0" class="form_item">
|
|
917
|
-
<van-collapse v-model="activeCollapseName" accordion>
|
|
918
|
-
<van-collapse-item title="副标题" name="副标题">
|
|
919
|
-
<van-form>
|
|
920
|
-
<van-cell-group inset>
|
|
921
|
-
<template v-for="(subCell, cellIndex) in activatedConfig.subTitle" :key="cellIndex">
|
|
922
|
-
<template v-if="subCell.type === 'inputs'">
|
|
923
|
-
<template v-for="(item, itemIndex) in formatInputs(subCell)" :key="itemIndex">
|
|
924
|
-
<van-field
|
|
925
|
-
v-model="activatedConfig.data[subCell.dataIndex][itemIndex]"
|
|
926
|
-
:label="`${item}:`"
|
|
927
|
-
clearable
|
|
928
|
-
type="textarea"
|
|
929
|
-
rows="1"
|
|
930
|
-
autosize
|
|
931
|
-
:placeholder="`请输入${item}`"
|
|
932
|
-
/>
|
|
933
|
-
</template>
|
|
934
|
-
</template>
|
|
935
|
-
<template v-else>
|
|
936
|
-
<van-field
|
|
937
|
-
v-model="activatedConfig.data[subCell.dataIndex]"
|
|
938
|
-
:label="`${subCell.format}:`"
|
|
939
|
-
clearable
|
|
940
|
-
type="textarea"
|
|
941
|
-
rows="1"
|
|
942
|
-
autosize
|
|
943
|
-
:placeholder="`请输入${subCell.format}`"
|
|
944
|
-
/>
|
|
945
|
-
</template>
|
|
946
|
-
</template>
|
|
947
|
-
</van-cell-group>
|
|
948
|
-
</van-form>
|
|
949
|
-
</van-collapse-item>
|
|
950
|
-
</van-collapse>
|
|
951
|
-
</div>
|
|
878
|
+
<!-- <div v-if="activatedConfig.subTitle && activatedConfig.subTitle.length > 0" class="form_item"> -->
|
|
879
|
+
<!-- <van-collapse v-model="activeCollapseName" accordion> -->
|
|
880
|
+
<!-- <van-collapse-item title="副标题" name="副标题"> -->
|
|
881
|
+
<!-- <van-form> -->
|
|
882
|
+
<!-- <van-cell-group inset> -->
|
|
883
|
+
<!-- <template v-for="(subCell, cellIndex) in activatedConfig.subTitle" :key="cellIndex"> -->
|
|
884
|
+
<!-- <template v-if="subCell.type === 'inputs'"> -->
|
|
885
|
+
<!-- <template v-for="(item, itemIndex) in formatInputs(subCell)" :key="itemIndex"> -->
|
|
886
|
+
<!-- <van-field -->
|
|
887
|
+
<!-- v-model="activatedConfig.data[subCell.dataIndex][itemIndex]" -->
|
|
888
|
+
<!-- :label="`${item}:`" -->
|
|
889
|
+
<!-- clearable -->
|
|
890
|
+
<!-- type="textarea" -->
|
|
891
|
+
<!-- rows="1" -->
|
|
892
|
+
<!-- autosize -->
|
|
893
|
+
<!-- :placeholder="`请输入${item}`" -->
|
|
894
|
+
<!-- /> -->
|
|
895
|
+
<!-- </template> -->
|
|
896
|
+
<!-- </template> -->
|
|
897
|
+
<!-- <template v-else> -->
|
|
898
|
+
<!-- <van-field -->
|
|
899
|
+
<!-- v-model="activatedConfig.data[subCell.dataIndex]" -->
|
|
900
|
+
<!-- :label="`${subCell.format}:`" -->
|
|
901
|
+
<!-- clearable -->
|
|
902
|
+
<!-- type="textarea" -->
|
|
903
|
+
<!-- rows="1" -->
|
|
904
|
+
<!-- autosize -->
|
|
905
|
+
<!-- :placeholder="`请输入${subCell.format}`" -->
|
|
906
|
+
<!-- /> -->
|
|
907
|
+
<!-- </template> -->
|
|
908
|
+
<!-- </template> -->
|
|
909
|
+
<!-- </van-cell-group> -->
|
|
910
|
+
<!-- </van-form> -->
|
|
911
|
+
<!-- </van-collapse-item> -->
|
|
912
|
+
<!-- </van-collapse> -->
|
|
913
|
+
<!-- </div> -->
|
|
952
914
|
<!-- 表单项 -->
|
|
953
915
|
<div class="form_item">
|
|
954
916
|
<van-collapse v-model="activeCollapseName" accordion>
|
|
955
|
-
<van-collapse-item title="
|
|
917
|
+
<van-collapse-item title="操作卡内容" name="操作卡内容">
|
|
956
918
|
<van-form>
|
|
957
919
|
<template v-for="(row, index) in activatedConfig.columns" :key="index">
|
|
958
920
|
<!-- value属性 -->
|
|
@@ -1020,7 +982,7 @@ function onCancelPicker() {
|
|
|
1020
982
|
{{ row.valueText || '当前时间' }}
|
|
1021
983
|
</div>
|
|
1022
984
|
<div class="cur-date-input-value">
|
|
1023
|
-
{{ activatedConfig.data[row.dataIndex] || '
|
|
985
|
+
{{ activatedConfig.data[row.dataIndex] || '未操作' }}
|
|
1024
986
|
</div>
|
|
1025
987
|
</div>
|
|
1026
988
|
<div class="cur-date-input-action">
|
|
@@ -1058,22 +1020,32 @@ function onCancelPicker() {
|
|
|
1058
1020
|
</van-cell-group>
|
|
1059
1021
|
<!-- datePicker -->
|
|
1060
1022
|
<van-cell-group v-else-if="row.type === 'datePicker'" inset :title="row.label" :class="{ 'required-field': row.required }">
|
|
1061
|
-
<
|
|
1023
|
+
<DateTimeSecondsPicker
|
|
1062
1024
|
v-model="activatedConfig.data[row.dataIndex]"
|
|
1063
1025
|
:label="`${row.label || '日期'}:`"
|
|
1064
1026
|
placeholder="请选择日期"
|
|
1065
|
-
|
|
1066
|
-
|
|
1027
|
+
title="选择日期"
|
|
1028
|
+
format="YYYY-MM-DD"
|
|
1067
1029
|
/>
|
|
1068
1030
|
</van-cell-group>
|
|
1069
1031
|
<!-- timePicker -->
|
|
1070
1032
|
<van-cell-group v-else-if="row.type === 'timePicker'" inset :title="row.label" :class="{ 'required-field': row.required }">
|
|
1071
|
-
<
|
|
1033
|
+
<DateTimeSecondsPicker
|
|
1072
1034
|
v-model="activatedConfig.data[row.dataIndex]"
|
|
1073
1035
|
:label="`${row.label || '时间'}:`"
|
|
1074
1036
|
placeholder="请选择时间"
|
|
1075
|
-
|
|
1076
|
-
|
|
1037
|
+
title="选择时间"
|
|
1038
|
+
format="YYYY-MM-DD HH:mm:ss"
|
|
1039
|
+
/>
|
|
1040
|
+
</van-cell-group>
|
|
1041
|
+
<!-- dateTimeSecondsPicker -->
|
|
1042
|
+
<van-cell-group v-else-if="row.type === 'dateTimeSecondsPicker'" inset :title="row.label" :class="{ 'required-field': row.required }">
|
|
1043
|
+
<DateTimeSecondsPicker
|
|
1044
|
+
v-model="activatedConfig.data[row.dataIndex]"
|
|
1045
|
+
:label="`${row.label || '完整时间'}:`"
|
|
1046
|
+
placeholder="请选择完整时间"
|
|
1047
|
+
title="选择完整时间"
|
|
1048
|
+
format="YYYY-MM-DD HH:mm:ss"
|
|
1077
1049
|
/>
|
|
1078
1050
|
</van-cell-group>
|
|
1079
1051
|
<!-- inputs -->
|
|
@@ -1235,31 +1207,29 @@ function onCancelPicker() {
|
|
|
1235
1207
|
<van-skeleton title :row="5" />
|
|
1236
1208
|
</div>
|
|
1237
1209
|
|
|
1238
|
-
<!--
|
|
1239
|
-
<VueHashCalendar v-model:visible="showDatePicker" format="YY-MM-DD" model="dialog" picker-type="date" @confirm="onConfirmDate" />
|
|
1240
|
-
<VueHashCalendar v-model:visible="showTimePicker" format="YY-MM-DD hh:mm:ss" picker-type="datetime" model="dialog" @confirm="onConfirmTime" />
|
|
1210
|
+
<!-- 已移除 VueHashCalendar,现在使用内置的 DateTimeSecondsPicker 组件 -->
|
|
1241
1211
|
</template>
|
|
1242
1212
|
|
|
1243
1213
|
<style scoped lang="less">
|
|
1244
|
-
.main{
|
|
1214
|
+
.main {
|
|
1245
1215
|
padding-top: 4vh;
|
|
1246
1216
|
width: 100vw;
|
|
1247
1217
|
height: 100vh;
|
|
1248
1218
|
background-color: #eff2f5;
|
|
1249
1219
|
|
|
1250
|
-
.title{
|
|
1220
|
+
.title {
|
|
1251
1221
|
padding-bottom: 2vh;
|
|
1252
1222
|
color: rgb(50, 50, 51);
|
|
1253
1223
|
text-align: center;
|
|
1254
1224
|
margin: 0 0 3vh;
|
|
1255
1225
|
}
|
|
1256
1226
|
|
|
1257
|
-
.text_box{
|
|
1227
|
+
.text_box {
|
|
1258
1228
|
margin-top: 2vh;
|
|
1259
1229
|
margin-bottom: 2vh;
|
|
1260
1230
|
}
|
|
1261
1231
|
|
|
1262
|
-
.main_text{
|
|
1232
|
+
.main_text {
|
|
1263
1233
|
padding-left: 16px;
|
|
1264
1234
|
font-weight: 400;
|
|
1265
1235
|
line-height: 1.6;
|
|
@@ -1268,53 +1238,53 @@ function onCancelPicker() {
|
|
|
1268
1238
|
font-size: 14px;
|
|
1269
1239
|
}
|
|
1270
1240
|
|
|
1271
|
-
.show_value_item{
|
|
1241
|
+
.show_value_item {
|
|
1272
1242
|
text-align: center;
|
|
1273
1243
|
font-size: 1.2em;
|
|
1274
1244
|
}
|
|
1275
1245
|
|
|
1276
|
-
.cell_group{
|
|
1246
|
+
.cell_group {
|
|
1277
1247
|
//margin-top: 2vh;
|
|
1278
1248
|
//margin-bottom: 2vh;
|
|
1279
1249
|
}
|
|
1280
1250
|
|
|
1281
|
-
.form_item{
|
|
1251
|
+
.form_item {
|
|
1282
1252
|
margin-top: 2vh;
|
|
1283
1253
|
}
|
|
1284
1254
|
|
|
1285
|
-
.button_group{
|
|
1255
|
+
.button_group {
|
|
1286
1256
|
text-align: center;
|
|
1287
1257
|
margin-top: 3vh;
|
|
1288
1258
|
margin-bottom: 3vh;
|
|
1289
1259
|
}
|
|
1290
1260
|
|
|
1291
|
-
.button_group
|
|
1261
|
+
.button_group > :first-child {
|
|
1292
1262
|
margin-right: 3vw;
|
|
1293
1263
|
}
|
|
1294
1264
|
|
|
1295
|
-
.divider{
|
|
1265
|
+
.divider {
|
|
1296
1266
|
color: #1989fa;
|
|
1297
1267
|
border-color: #1989fa;
|
|
1298
|
-
padding: 0 16px
|
|
1268
|
+
padding: 0 16px;
|
|
1299
1269
|
}
|
|
1300
1270
|
|
|
1301
|
-
.submit_button{
|
|
1271
|
+
.submit_button {
|
|
1302
1272
|
background-color: #eff2f5;
|
|
1303
1273
|
padding: 5vh;
|
|
1304
1274
|
}
|
|
1305
1275
|
}
|
|
1306
1276
|
|
|
1307
|
-
.skeleton{
|
|
1308
|
-
margin-top: 5vh
|
|
1277
|
+
.skeleton {
|
|
1278
|
+
margin-top: 5vh;
|
|
1309
1279
|
}
|
|
1310
|
-
.my-cell-group{
|
|
1311
|
-
margin: 0 0 10px 0
|
|
1280
|
+
.my-cell-group {
|
|
1281
|
+
margin: 0 0 10px 0;
|
|
1312
1282
|
}
|
|
1313
1283
|
:deep(.van-collapse-item__content) {
|
|
1314
1284
|
background-color: #eff2f5;
|
|
1315
1285
|
padding: 10px 0;
|
|
1316
1286
|
}
|
|
1317
|
-
:deep(.van-cell-group__title){
|
|
1287
|
+
:deep(.van-cell-group__title) {
|
|
1318
1288
|
padding-top: 10px;
|
|
1319
1289
|
padding-bottom: 10px;
|
|
1320
1290
|
}
|
|
@@ -1325,7 +1295,7 @@ function onCancelPicker() {
|
|
|
1325
1295
|
// 必填字段星号样式 - 只对星号生效
|
|
1326
1296
|
:deep(.van-field__label) {
|
|
1327
1297
|
// 将包含星号的文本进行特殊处理
|
|
1328
|
-
&[style*=
|
|
1298
|
+
&[style*='color'] {
|
|
1329
1299
|
color: #323233 !important;
|
|
1330
1300
|
}
|
|
1331
1301
|
}
|
|
@@ -1340,7 +1310,7 @@ function onCancelPicker() {
|
|
|
1340
1310
|
margin-right: 2px;
|
|
1341
1311
|
}
|
|
1342
1312
|
}
|
|
1343
|
-
:deep(.van-uploader__wrapper){
|
|
1313
|
+
:deep(.van-uploader__wrapper) {
|
|
1344
1314
|
padding: 10px;
|
|
1345
1315
|
display: flex;
|
|
1346
1316
|
flex-wrap: wrap;
|
|
@@ -1371,7 +1341,7 @@ function onCancelPicker() {
|
|
|
1371
1341
|
word-wrap: break-word;
|
|
1372
1342
|
white-space: normal;
|
|
1373
1343
|
display: -webkit-box;
|
|
1374
|
-
-webkit-line-clamp:
|
|
1344
|
+
-webkit-line-clamp: 4; // 最多显示2行
|
|
1375
1345
|
-webkit-box-orient: vertical;
|
|
1376
1346
|
overflow: hidden;
|
|
1377
1347
|
}
|
package/src/styles/app.less
CHANGED
|
@@ -6,9 +6,16 @@ import { ref } from 'vue'
|
|
|
6
6
|
import { useRoute } from 'vue-router'
|
|
7
7
|
|
|
8
8
|
// 纯表单
|
|
9
|
-
const configName = ref('
|
|
9
|
+
const configName = ref('testFormGroup')
|
|
10
10
|
const serviceName = ref('af-apply')
|
|
11
11
|
|
|
12
|
+
// const configName = ref("计划下发Form")
|
|
13
|
+
// const serviceName = ref("af-linepatrol")
|
|
14
|
+
|
|
15
|
+
// 表单组
|
|
16
|
+
// const configName = ref('lngChargeAuditMobileFormGroup')
|
|
17
|
+
// const serviceName = ref('af-gaslink')
|
|
18
|
+
|
|
12
19
|
const formData = ref({})
|
|
13
20
|
const formGroup = ref(null)
|
|
14
21
|
const route = useRoute()
|
|
@@ -18,6 +25,36 @@ function submit(_result) {
|
|
|
18
25
|
history.back()
|
|
19
26
|
})
|
|
20
27
|
}
|
|
28
|
+
|
|
29
|
+
// 表单组——数据
|
|
30
|
+
// function initComponents () {
|
|
31
|
+
// runLogic('getlngChargeAuditMobileFormGroupData', {id: 29}, 'af-gaslink').then((res) => {
|
|
32
|
+
// formData.value = {...res}
|
|
33
|
+
// })
|
|
34
|
+
// }
|
|
35
|
+
|
|
36
|
+
// 纯表单——数据
|
|
37
|
+
// function initComponents() {
|
|
38
|
+
// formData.value = { plan_name: 'af-llllll', plan_point: '1号点位', plan_single: '1号点位', plan_range: '2024-12-12' }
|
|
39
|
+
// }
|
|
40
|
+
|
|
41
|
+
// function initComponents() {
|
|
42
|
+
// runLogic('getlngChargeAuditMobileFormGroupData', { id: route.query?.id, o_id: route.query?.o_id }, 'af-gaslink').then((res) => {
|
|
43
|
+
// console.log('res------', res)
|
|
44
|
+
// formData.value = { ...res }
|
|
45
|
+
// formGroup.value.init({
|
|
46
|
+
// configName: configName.value,
|
|
47
|
+
// serviceName: serviceName.value,
|
|
48
|
+
// groupFormData: { ...res },
|
|
49
|
+
// mode: "新增"
|
|
50
|
+
// })
|
|
51
|
+
// isInit.value = true
|
|
52
|
+
// })
|
|
53
|
+
// }
|
|
54
|
+
|
|
55
|
+
// onBeforeMount(() => {
|
|
56
|
+
// initComponents()
|
|
57
|
+
// })
|
|
21
58
|
</script>
|
|
22
59
|
|
|
23
60
|
<template>
|