generated from Leo_Ding/web-template
1
This commit is contained in:
parent
65caeb0f1a
commit
acf29dd294
107
package-lock.json
generated
107
package-lock.json
generated
@ -12,6 +12,7 @@
|
||||
"@ant-design/colors": "^7.0.0",
|
||||
"@ant-design/icons-vue": "^6.1.0",
|
||||
"@icon-park/vue-next": "^1.4.2",
|
||||
"@jiaminghi/data-view": "^2.10.0",
|
||||
"@tinymce/tinymce-vue": "^5.1.0",
|
||||
"ant-design-vue": "^4.0.1",
|
||||
"axios": "^1.4.0",
|
||||
@ -904,6 +905,62 @@
|
||||
"url": "https://github.com/sponsors/kazupon"
|
||||
}
|
||||
},
|
||||
"node_modules/@jiaminghi/bezier-curve": {
|
||||
"version": "0.0.9",
|
||||
"resolved": "https://registry.npmmirror.com/@jiaminghi/bezier-curve/-/bezier-curve-0.0.9.tgz",
|
||||
"integrity": "sha512-u9xJPOEl6Dri2E9FfmJoGxYQY7vYJkURNX04Vj64tdi535tPrpkuf9Sm0lNr3QTKdHQh0DdNRsaa62FLQNQEEw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.5.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@jiaminghi/c-render": {
|
||||
"version": "0.4.3",
|
||||
"resolved": "https://registry.npmmirror.com/@jiaminghi/c-render/-/c-render-0.4.3.tgz",
|
||||
"integrity": "sha512-FJfzj5hGj7MLqqqI2D7vEzHKbQ1Ynnn7PJKgzsjXaZpJzTqs2Yw5OSeZnm6l7Qj7jyPAP53lFvEQNH4o4j6s+Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"@jiaminghi/bezier-curve": "*",
|
||||
"@jiaminghi/color": "*",
|
||||
"@jiaminghi/transition": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@jiaminghi/charts": {
|
||||
"version": "0.2.18",
|
||||
"resolved": "https://registry.npmmirror.com/@jiaminghi/charts/-/charts-0.2.18.tgz",
|
||||
"integrity": "sha512-K+HXaOOeWG9OOY1VG6M4mBreeeIAPhb9X+khG651AbnwEwL6G2UtcAQ8GWCq6GzhczcLwwhIhuaHqRygwHC0sA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"@jiaminghi/c-render": "^0.4.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@jiaminghi/color": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmmirror.com/@jiaminghi/color/-/color-1.1.3.tgz",
|
||||
"integrity": "sha512-ZY3hdorgODk4OSTbxyXBPxAxHPIVf9rPlKJyK1C1db46a50J0reFKpAvfZG8zMG3lvM60IR7Qawgcu4ZDO3+Hg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@jiaminghi/data-view": {
|
||||
"version": "2.10.0",
|
||||
"resolved": "https://registry.npmmirror.com/@jiaminghi/data-view/-/data-view-2.10.0.tgz",
|
||||
"integrity": "sha512-Cud2MTiMcqc5k2KWabR/svuVQmXHANqURo+yj40370/LdI/gyUJ6LG203hWXEnT1nMCeiv/SLVmxv3PXLScCeA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"@jiaminghi/charts": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@jiaminghi/transition": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmmirror.com/@jiaminghi/transition/-/transition-1.1.11.tgz",
|
||||
"integrity": "sha512-owBggipoHMikDHHDW5Gc7RZYlVuvxHADiU4bxfjBVkHDAmmck+fCkm46n2JzC3j33hWvP9nSCAeh37t6stgWeg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.5.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/sourcemap-codec": {
|
||||
"version": "1.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
|
||||
@ -5557,6 +5614,56 @@
|
||||
"resolved": "https://registry.npmmirror.com/@intlify/shared/-/shared-9.14.4.tgz",
|
||||
"integrity": "sha512-P9zv6i1WvMc9qDBWvIgKkymjY2ptIiQ065PjDv7z7fDqH3J/HBRBN5IoiR46r/ujRcU7hCuSIZWvCAFCyuOYZA=="
|
||||
},
|
||||
"@jiaminghi/bezier-curve": {
|
||||
"version": "0.0.9",
|
||||
"resolved": "https://registry.npmmirror.com/@jiaminghi/bezier-curve/-/bezier-curve-0.0.9.tgz",
|
||||
"integrity": "sha512-u9xJPOEl6Dri2E9FfmJoGxYQY7vYJkURNX04Vj64tdi535tPrpkuf9Sm0lNr3QTKdHQh0DdNRsaa62FLQNQEEw==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.5.5"
|
||||
}
|
||||
},
|
||||
"@jiaminghi/c-render": {
|
||||
"version": "0.4.3",
|
||||
"resolved": "https://registry.npmmirror.com/@jiaminghi/c-render/-/c-render-0.4.3.tgz",
|
||||
"integrity": "sha512-FJfzj5hGj7MLqqqI2D7vEzHKbQ1Ynnn7PJKgzsjXaZpJzTqs2Yw5OSeZnm6l7Qj7jyPAP53lFvEQNH4o4j6s+Q==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"@jiaminghi/bezier-curve": "*",
|
||||
"@jiaminghi/color": "*",
|
||||
"@jiaminghi/transition": "*"
|
||||
}
|
||||
},
|
||||
"@jiaminghi/charts": {
|
||||
"version": "0.2.18",
|
||||
"resolved": "https://registry.npmmirror.com/@jiaminghi/charts/-/charts-0.2.18.tgz",
|
||||
"integrity": "sha512-K+HXaOOeWG9OOY1VG6M4mBreeeIAPhb9X+khG651AbnwEwL6G2UtcAQ8GWCq6GzhczcLwwhIhuaHqRygwHC0sA==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"@jiaminghi/c-render": "^0.4.3"
|
||||
}
|
||||
},
|
||||
"@jiaminghi/color": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmmirror.com/@jiaminghi/color/-/color-1.1.3.tgz",
|
||||
"integrity": "sha512-ZY3hdorgODk4OSTbxyXBPxAxHPIVf9rPlKJyK1C1db46a50J0reFKpAvfZG8zMG3lvM60IR7Qawgcu4ZDO3+Hg=="
|
||||
},
|
||||
"@jiaminghi/data-view": {
|
||||
"version": "2.10.0",
|
||||
"resolved": "https://registry.npmmirror.com/@jiaminghi/data-view/-/data-view-2.10.0.tgz",
|
||||
"integrity": "sha512-Cud2MTiMcqc5k2KWabR/svuVQmXHANqURo+yj40370/LdI/gyUJ6LG203hWXEnT1nMCeiv/SLVmxv3PXLScCeA==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"@jiaminghi/charts": "*"
|
||||
}
|
||||
},
|
||||
"@jiaminghi/transition": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmmirror.com/@jiaminghi/transition/-/transition-1.1.11.tgz",
|
||||
"integrity": "sha512-owBggipoHMikDHHDW5Gc7RZYlVuvxHADiU4bxfjBVkHDAmmck+fCkm46n2JzC3j33hWvP9nSCAeh37t6stgWeg==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.5.5"
|
||||
}
|
||||
},
|
||||
"@jridgewell/sourcemap-codec": {
|
||||
"version": "1.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
"@ant-design/colors": "^7.0.0",
|
||||
"@ant-design/icons-vue": "^6.1.0",
|
||||
"@icon-park/vue-next": "^1.4.2",
|
||||
"@jiaminghi/data-view": "^2.10.0",
|
||||
"@tinymce/tinymce-vue": "^5.1.0",
|
||||
"ant-design-vue": "^4.0.1",
|
||||
"axios": "^1.4.0",
|
||||
|
||||
19
src/apis/modules/projectType.js
Normal file
19
src/apis/modules/projectType.js
Normal file
@ -0,0 +1,19 @@
|
||||
/**
|
||||
* 区域模块接口
|
||||
*/
|
||||
import request from '@/utils/request'
|
||||
// 获取项目列表
|
||||
export const getProjectList = (params) => request.basic.get('/api/v1/service-project-categories', params)
|
||||
// 获取单挑数据
|
||||
export const getItem = (id) => request.basic.get(`/api/v1/service-project-categories/${id}`)
|
||||
// 添加条目
|
||||
export const createItem = (params) => request.basic.post('/api/v1/service-project-categories', params)
|
||||
// 更新role
|
||||
export const updateItem = (params) => request.basic.put(`/api/v1/service-project-categories/${params.id}`, params)
|
||||
// 删除数据
|
||||
export const delItem = (id) => request.basic.delete(`/api/v1/service-project-categories/${id}`)
|
||||
export const getProjectListAll = (params) => request.basic.get('/api/v1/service-project-categories/all',params)
|
||||
|
||||
|
||||
|
||||
|
||||
@ -16,3 +16,5 @@ export const delItem = (id) => request.basic.delete(`/api/v1/customers/${id}`)
|
||||
//获取用户数量
|
||||
export const getCount=(params)=>request.basic.get('/api/v1/customers/count',params)
|
||||
|
||||
//创建工单
|
||||
export const createOrderItem=(params)=> request.basic.post('/api/v1/orders', params)
|
||||
19
src/apis/modules/serviceProject.js
Normal file
19
src/apis/modules/serviceProject.js
Normal file
@ -0,0 +1,19 @@
|
||||
/**
|
||||
* 区域模块接口
|
||||
*/
|
||||
import request from '@/utils/request'
|
||||
// 获取项目列表
|
||||
export const getProjectList = (params) => request.basic.get('/api/v1/service-projects', params)
|
||||
// 获取单挑数据
|
||||
export const getItem = (id) => request.basic.get(`/api/v1/service-projects/${id}`)
|
||||
// 添加条目
|
||||
export const createItem = (params) => request.basic.post('/api/v1/service-projects', params)
|
||||
// 更新role
|
||||
export const updateItem = (params) => request.basic.put(`/api/v1/service-projects/${params.id}`, params)
|
||||
// 删除数据
|
||||
export const delItem = (id) => request.basic.delete(`/api/v1/service-projects/${id}`)
|
||||
export const getProjectListAll = (params) => request.basic.get('/api/v1/service-projects/all', params)
|
||||
|
||||
|
||||
|
||||
|
||||
BIN
src/assets/imgs/bg2.png
Normal file
BIN
src/assets/imgs/bg2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 513 KiB |
BIN
src/assets/imgs/screenbg.png
Normal file
BIN
src/assets/imgs/screenbg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 MiB |
@ -1,114 +1,146 @@
|
||||
<!-- AreaCascader.vue -->
|
||||
<template>
|
||||
<a-cascader v-model:value="modelValue" :options="options" :load-data="loadData" :placeholder="placeholder"
|
||||
:style="style" :disabled="disabled" :show-search="showSearch" :allow-clear="allowClear"
|
||||
:change-on-select="changeOnSelect" :field-names="fieldNames" @change="handleChange" />
|
||||
<a-cascader
|
||||
v-model:value="modelValue"
|
||||
:options="options"
|
||||
:load-data="loadData"
|
||||
:placeholder="placeholder"
|
||||
:style="style"
|
||||
:disabled="disabled"
|
||||
:show-search="showSearch"
|
||||
:allow-clear="allowClear"
|
||||
:change-on-select="changeOnSelect"
|
||||
:field-names="fieldNames"
|
||||
@change="handleChange"
|
||||
ref="cascaderRef"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, watch, onMounted,defineModel } from 'vue';
|
||||
import apis from '@/apis'
|
||||
import { useDicsStore } from '@/store'
|
||||
const dicsStore = useDicsStore()
|
||||
// 使用 defineModel 自动处理 v-model
|
||||
import { ref, watch, nextTick, defineModel, onMounted } from 'vue';
|
||||
import apis from '@/apis';
|
||||
import { useDicsStore } from '@/store';
|
||||
|
||||
const dicsStore = useDicsStore();
|
||||
const modelValue = defineModel();
|
||||
// 接收 props
|
||||
const props = defineProps({
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请选择省市区'
|
||||
},
|
||||
style: {
|
||||
type: Object,
|
||||
default: () => ({ width: '100%' })
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
showSearch: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
allowClear: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
changeOnSelect: {
|
||||
type: Boolean,
|
||||
default: false // 通常只在最后一级选择后触发
|
||||
},
|
||||
fieldNames: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
label: 'label',
|
||||
value: 'code',
|
||||
// children: 'children'
|
||||
})
|
||||
}
|
||||
placeholder: { type: String, default: '请选择省市区' },
|
||||
style: { type: Object, default: () => ({ width: '100%' }) },
|
||||
disabled: { type: Boolean, default: false },
|
||||
showSearch: { type: Boolean, default: true },
|
||||
allowClear: { type: Boolean, default: true },
|
||||
changeOnSelect: { type: Boolean, default: false },
|
||||
fieldNames: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
label: 'label',
|
||||
value: 'code',
|
||||
// children: 'children' // 注意:如果后端字段是 children,可以放开
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
// 定义 emit
|
||||
const emit = defineEmits(['change']);
|
||||
|
||||
// 本地选项数据(初始为空,异步加载)
|
||||
const options = ref([]);
|
||||
|
||||
// 🔁 监听 store 的省份数据
|
||||
watch(
|
||||
() => dicsStore.provinceOptions,
|
||||
(newVal) => {
|
||||
if (newVal && newVal.length > 0) {
|
||||
options.value = newVal
|
||||
options.value = newVal;
|
||||
}
|
||||
},
|
||||
{ immediate: true } // 🔥 关键:组件初始化时也会执行一次
|
||||
)
|
||||
// onMounted(async () => {
|
||||
// // 使用 store 中的省份数据
|
||||
// options.value = await dicsStore.provinceOptions
|
||||
// });
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
// 🔁 监听 modelValue,实现自动回显(关键优化)
|
||||
watch(
|
||||
() => modelValue?.value,
|
||||
async (val) => {
|
||||
if (!val || !Array.isArray(val) || val.length <= 1) return;
|
||||
|
||||
// 异步加载子节点(市、区)
|
||||
const loadData = async (selectedOptions) => {
|
||||
console.log('加载子节点, 选中选项:', selectedOptions);
|
||||
const targetOption = selectedOptions[selectedOptions.length - 1];
|
||||
targetOption.loading = true;
|
||||
// 等待组件初始化
|
||||
await nextTick();
|
||||
|
||||
try {
|
||||
const response = await apis.common.getAreaList({ current:1,pageSize:100,parentId: targetOption.id });
|
||||
// 从第二级开始,逐级模拟加载
|
||||
for (let i = 1; i < val.length; i++) {
|
||||
const parentCode = val[i - 1];
|
||||
const currentCode = val[i];
|
||||
|
||||
targetOption.loading = false;
|
||||
// 查找当前选中的父节点
|
||||
let targetNode;
|
||||
if (i === 1) {
|
||||
// 第一级(省)在 options 中
|
||||
targetNode = options.value.find(opt => opt.code === parentCode);
|
||||
} else {
|
||||
// 更深层级,需要递归查找
|
||||
targetNode = findNodeInOptions(options.value, parentCode);
|
||||
}
|
||||
|
||||
if (Array.isArray(response.data)) {
|
||||
const children = response.data.map(item => ({
|
||||
...item,
|
||||
isLeaf: !item.hasChild // 区/县 级别设为叶子节点
|
||||
}));
|
||||
if (targetNode && !targetNode.children) {
|
||||
// 触发 loadData 加载子级
|
||||
await loadData([targetNode]);
|
||||
}
|
||||
|
||||
// 更新 children
|
||||
targetOption.children = children;
|
||||
} else {
|
||||
targetOption.children = [];
|
||||
}
|
||||
|
||||
// 触发视图更新
|
||||
options.value = [...options.value];
|
||||
} catch (error) {
|
||||
console.error('加载子节点失败:', error);
|
||||
targetOption.children = [];
|
||||
targetOption.loading = false;
|
||||
// 等待加载完成
|
||||
await nextTick();
|
||||
}
|
||||
},
|
||||
{ immediate: true } // 🔥 确保编辑时能立即触发
|
||||
);
|
||||
|
||||
// 🔍 递归查找节点
|
||||
function findNodeInOptions(options, code) {
|
||||
for (const opt of options) {
|
||||
if (opt.code === code) return opt;
|
||||
if (opt.children) {
|
||||
const found = findNodeInOptions(opt.children, code);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// 🌐 异步加载子节点
|
||||
const loadData = async (selectedOptions) => {
|
||||
const targetOption = selectedOptions[selectedOptions.length - 1];
|
||||
targetOption.loading = true;
|
||||
|
||||
try {
|
||||
const parentId = targetOption.id || targetOption.code; // 兼容 id 或 code
|
||||
const response = await apis.common.getAreaList({
|
||||
current: 1,
|
||||
pageSize: 100,
|
||||
parentId
|
||||
});
|
||||
|
||||
targetOption.loading = false;
|
||||
|
||||
if (Array.isArray(response.data)) {
|
||||
const children = response.data.map(item => ({
|
||||
...item,
|
||||
isLeaf: !item.hasChild,
|
||||
label: item.label || item.name, // 兼容字段
|
||||
value: item.code
|
||||
}));
|
||||
|
||||
targetOption.children = children;
|
||||
} else {
|
||||
targetOption.children = [];
|
||||
}
|
||||
|
||||
// 触发视图更新
|
||||
options.value = [...options.value];
|
||||
} catch (error) {
|
||||
console.error('加载子节点失败:', error);
|
||||
targetOption.children = [];
|
||||
targetOption.loading = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 处理选择变化
|
||||
// 📣 处理选择变化
|
||||
const handleChange = (value, selectedOptions) => {
|
||||
emit('change', value, selectedOptions.map(option => option.label));
|
||||
emit('change', value, selectedOptions?.map(opt => opt.label) || []);
|
||||
};
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 可根据需要添加样式 */
|
||||
</style>
|
||||
@ -235,12 +235,14 @@ const clearMarkers = () => {
|
||||
searchResult.value = null;
|
||||
};
|
||||
const handleChange=(e)=>{
|
||||
console.log(searchList.value)
|
||||
const item = searchList.value.find(item=>item.id===e)
|
||||
const obj={
|
||||
lng:item.location.lng,
|
||||
lat:item.location.lat,
|
||||
addres:item.address
|
||||
addres:item.name
|
||||
}
|
||||
console.log(obj)
|
||||
emit('handleGetLng', obj)
|
||||
}
|
||||
</script>
|
||||
|
||||
0
src/components/serverStation/index.vue
Normal file
0
src/components/serverStation/index.vue
Normal file
@ -1,23 +1,21 @@
|
||||
<template>
|
||||
<a-layout-header
|
||||
class="basic-header"
|
||||
:class="cpClassNames"
|
||||
:style="cpStyles">
|
||||
<a-layout-header class="basic-header" :class="cpClassNames" :style="cpStyles">
|
||||
<!-- 左侧 -->
|
||||
<div
|
||||
v-if="cpShowLeftSlot"
|
||||
class="basic-header__left">
|
||||
<div v-if="cpShowLeftSlot" class="basic-header__left">
|
||||
<slot name="left"></slot>
|
||||
</div>
|
||||
<!-- 中间 -->
|
||||
<div
|
||||
v-if="cpShowDefaultSlot"
|
||||
class="basic-header__center">
|
||||
<div v-if="cpShowDefaultSlot" class="basic-header__center">
|
||||
<slot></slot>
|
||||
</div>
|
||||
<!-- 右侧 -->
|
||||
<div class="basic-header__right">
|
||||
<a-space :size="16">
|
||||
<a-tooltip title="居家服务数据大屏">
|
||||
<action-button @click="handleBigScreen">
|
||||
<BarChartOutlined />
|
||||
</action-button>
|
||||
</a-tooltip>
|
||||
<action-button @click="handleConfig">
|
||||
<setting-outlined></setting-outlined>
|
||||
</action-button>
|
||||
@ -28,10 +26,7 @@
|
||||
<a-spin />
|
||||
<template #overlay>
|
||||
<a-menu v-model:selectedKeys="current">
|
||||
<a-menu-item
|
||||
v-for="(item, key) in langData"
|
||||
:key="key"
|
||||
@click="handleLang(key)">
|
||||
<a-menu-item v-for="(item, key) in langData" :key="key" @click="handleLang(key)">
|
||||
{{ item.icon }} {{ item.label }}
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
@ -40,9 +35,7 @@
|
||||
|
||||
<a-dropdown :trigger="['click']">
|
||||
<action-button :style="{ height: '44px' }">
|
||||
<a-avatar
|
||||
class="mr-8-1 display-inline-flex justify-content-center"
|
||||
:size="24"
|
||||
<a-avatar class="mr-8-1 display-inline-flex justify-content-center" :size="24"
|
||||
:src="userInfo?.avatar">
|
||||
</a-avatar>
|
||||
<span>{{ userInfo?.name }}</span>
|
||||
@ -50,15 +43,11 @@
|
||||
<a-spin />
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item
|
||||
key="edit"
|
||||
@click="handleOpen">
|
||||
<a-menu-item key="edit" @click="handleOpen">
|
||||
<edit-outlined />
|
||||
{{ $t('component.RightContent.profile') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item
|
||||
key="logout"
|
||||
@click="handleLogout">
|
||||
<a-menu-item key="logout" @click="handleLogout">
|
||||
<login-outlined></login-outlined>
|
||||
{{ $t('component.RightContent.logout') }}
|
||||
</a-menu-item>
|
||||
@ -75,7 +64,7 @@ import { Modal } from 'ant-design-vue'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { computed, useSlots, ref } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { LoginOutlined, SettingOutlined, EditOutlined, TranslationOutlined } from '@ant-design/icons-vue'
|
||||
import { LoginOutlined, SettingOutlined, EditOutlined, TranslationOutlined, BarChartOutlined } from '@ant-design/icons-vue'
|
||||
import { useAppStore, useUserStore } from '@/store'
|
||||
import ActionButton from './ActionButton.vue'
|
||||
import { theme as antTheme } from 'ant-design-vue'
|
||||
|
||||
@ -3,8 +3,10 @@ import {spliceUrl} from '@/utils/util'
|
||||
import App from '@/App.vue'
|
||||
import { useCore } from '@/core'
|
||||
import './assets/iconfont/iconfont.css';
|
||||
// import dataV from '@jiaminghi/data-view'
|
||||
|
||||
const app = createApp(App)
|
||||
// app.use(dataV)
|
||||
app.config.globalProperties.$spliceUrl=spliceUrl
|
||||
useCore(app)
|
||||
app.mount('#app')
|
||||
|
||||
@ -55,4 +55,12 @@ export const constantRoutes = [
|
||||
title: '平台选择',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/bigScreen',
|
||||
name: 'bigScreen',
|
||||
component: () => import('@/views/login/bigScreen.vue'),
|
||||
meta: {
|
||||
title: '居家服务数据大屏',
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
@ -15,6 +15,7 @@ import severObj from './severObj'
|
||||
import workorder from './workorder'
|
||||
import service from './service'
|
||||
import serviceStaff from './serviceStaff'
|
||||
import serverSet from './serverSet'
|
||||
export default [
|
||||
...home,
|
||||
// ...form,
|
||||
@ -32,5 +33,6 @@ export default [
|
||||
// ...other,
|
||||
...workorder,
|
||||
...service,
|
||||
...serviceStaff
|
||||
...serviceStaff,
|
||||
...serverSet
|
||||
]
|
||||
|
||||
@ -20,7 +20,6 @@ const options = {
|
||||
},
|
||||
interceptorRequestCatch: () => {},
|
||||
interceptorResponse: (response) => {
|
||||
console.log('返回',response.data)
|
||||
// 错误处理
|
||||
const { success, msg = 'Network Error' } = response.data || {}
|
||||
if (![true].includes(success)) {
|
||||
|
||||
@ -1,180 +0,0 @@
|
||||
<template>
|
||||
<a-modal :open="modal.open" :title="modal.title" :width="600" :confirm-loading="modal.confirmLoading"
|
||||
:after-close="onAfterClose" :cancel-text="cancelText" @ok="handleOk" @cancel="handleCancel">
|
||||
<a-card>
|
||||
<a-form ref="formRef" :model="formData" :rules="formRules">
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="姓名" name="name">
|
||||
<a-input v-model:value="formData.name" placeholder="请输入姓名" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<!-- 性别 -->
|
||||
<a-col :span="12">
|
||||
<a-form-item label="性别" name="gender">
|
||||
<a-radio-group v-model:value="formData.gender">
|
||||
<a-radio value="1">男</a-radio>
|
||||
<a-radio value="2">女</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<!-- 证件号码 -->
|
||||
<a-col :span="12">
|
||||
<a-form-item label="身份证号" name="idCard">
|
||||
<a-input v-model:value="formData.idCard" placeholder="请输入证件号码" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="电话" name="phone">
|
||||
<a-input v-model:value="formData.phone" placeholder="请输入电话" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="电话" name="phone">
|
||||
<a-input v-model:value="formData.phone" placeholder="请输入电话" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="护理人员类型" name="serviceType">
|
||||
<a-select v-model:value="formData.serviceType" allowClear>
|
||||
<a-select-option v-for="item in dicsStore.dictOptions.STAFF_TYPE" :key="item.dval"
|
||||
:value="item.dval">{{
|
||||
item.introduction }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="护理人员状态" name="status">
|
||||
<a-select v-model:value="formData.status" allowClear>
|
||||
<a-select-option v-for="item in dicsStore.dictOptions.STAFF_STATUS" :key="item.dval"
|
||||
:value="item.dval">{{
|
||||
item.introduction }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="用工形式" name="workType">
|
||||
<a-select v-model:value="formData.workType" allowClear>
|
||||
<a-select-option v-for="item in dicsStore.dictOptions.USE_TYPE" :key="item.dval"
|
||||
:value="item.dval">{{
|
||||
item.introduction }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="所属服务组织" name="stationLables">
|
||||
<node-tree v-model:value="formData.stationLables" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<!-- <a-col :span="8">
|
||||
<a-form-item label="组织所在区域" name="areaLabels">
|
||||
<node-tree v-model:value="formData.areaLabels" />
|
||||
</a-form-item>
|
||||
</a-col> -->
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-card>
|
||||
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { ref, defineProps } from 'vue'
|
||||
import { config } from '@/config'
|
||||
import apis from '@/apis'
|
||||
import { useForm, useModal } from '@/hooks'
|
||||
import { useDicsStore } from '@/store'
|
||||
import AreaCascader from '@/components/AreaCascader/index.vue'
|
||||
import NodeTree from '@/components/NodeTree/index.vue'
|
||||
const emit = defineEmits(['ok'])
|
||||
const activeKey = ref('1')
|
||||
const { modal, showModal, hideModal, showLoading, hideLoading } = useModal()
|
||||
const { formRecord, formData, formRef, formRules, resetForm } = useForm()
|
||||
const cancelText = ref('取消')
|
||||
const dicsStore = useDicsStore()
|
||||
|
||||
|
||||
/**
|
||||
* 新建
|
||||
*/
|
||||
function handleCreate() {
|
||||
showModal({
|
||||
type: 'create',
|
||||
title: '新增服务人员',
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 编辑
|
||||
*/
|
||||
function handleEdit(record = {}) {
|
||||
showModal({
|
||||
type: 'edit',
|
||||
title: '编辑项',
|
||||
})
|
||||
formRecord.value = record
|
||||
formData.value = cloneDeep(record)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 确定
|
||||
*/
|
||||
function handleOk() {
|
||||
formRef.value
|
||||
.validateFields()
|
||||
.then(async (values) => {
|
||||
try {
|
||||
showLoading()
|
||||
const params = {
|
||||
...formData.value,
|
||||
}
|
||||
let result = null
|
||||
switch (modal.value.type) {
|
||||
case 'create':
|
||||
result = await apis.serverObj.createItem(params).catch(() => {
|
||||
throw new Error()
|
||||
})
|
||||
break
|
||||
case 'edit':
|
||||
result = await apis.serverObj.updateItem(params).catch(() => {
|
||||
throw new Error()
|
||||
})
|
||||
break
|
||||
}
|
||||
hideLoading()
|
||||
if (config('http.code.success') === result?.code) {
|
||||
hideModal()
|
||||
emit('ok')
|
||||
}
|
||||
} catch (error) {
|
||||
hideLoading()
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
hideLoading()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消
|
||||
*/
|
||||
function handleCancel() {
|
||||
hideModal()
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭后
|
||||
*/
|
||||
function onAfterClose() {
|
||||
resetForm()
|
||||
hideLoading()
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
handleEdit,
|
||||
handleCreate,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
143
src/views/baseSet/serverProjectManage/components/EditDialog.vue
Normal file
143
src/views/baseSet/serverProjectManage/components/EditDialog.vue
Normal file
@ -0,0 +1,143 @@
|
||||
<template>
|
||||
<a-modal :open="modal.open" :title="modal.title" :width="600" :confirm-loading="modal.confirmLoading"
|
||||
:after-close="onAfterClose" :cancel-text="cancelText" @ok="handleOk" @cancel="handleCancel">
|
||||
<a-card>
|
||||
<a-form ref="formRef" :model="formData" :rules="formRules">
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="24">
|
||||
<a-form-item label="类型" name="categoryType">
|
||||
<a-select v-model:value="formData.categoryType" allowClear>
|
||||
<a-select-option v-for="item in dicsStore.dictOptions.PROJECT_TYPE" :key="item.dval"
|
||||
:value="item.dval">{{
|
||||
item.introduction }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="项目类型名称" name="name">
|
||||
<a-input v-model:value="formData.name" placeholder="请输入项目类型名称"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="分类描述" name="remark">
|
||||
<a-input v-model:value="formData.remark"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item :label="'状态'" name="status">
|
||||
<a-radio-group v-model:value="formData.status" :options="[
|
||||
{ label: '启用', value: 'enabled' },
|
||||
{ label: '停用', value: 'disabled' },
|
||||
]"></a-radio-group>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-card>
|
||||
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { ref, defineProps } from 'vue'
|
||||
import { config } from '@/config'
|
||||
import apis from '@/apis'
|
||||
import { useForm, useModal } from '@/hooks'
|
||||
import { useDicsStore } from '@/store'
|
||||
import { message } from 'ant-design-vue'
|
||||
const emit = defineEmits(['ok'])
|
||||
|
||||
const { modal, showModal, hideModal, showLoading, hideLoading } = useModal()
|
||||
const { formRecord, formData, formRef, formRules, resetForm } = useForm()
|
||||
const cancelText = ref('取消')
|
||||
const dicsStore = useDicsStore()
|
||||
formRules.value = {
|
||||
categoryType: [{ required: true, message: '请选择类型', trigger: ['blur', 'change'] }],
|
||||
name: [{ required: true, message: '请输入项目分类名称', trigger: 'blur' }],
|
||||
}
|
||||
|
||||
/**
|
||||
* 新建
|
||||
*/
|
||||
function handleCreate() {
|
||||
showModal({
|
||||
type: 'create',
|
||||
title: '新增项目分类',
|
||||
})
|
||||
formData.value.status='enabled'
|
||||
}
|
||||
/**
|
||||
* 编辑
|
||||
*/
|
||||
function handleEdit(record = {}) {
|
||||
showModal({
|
||||
type: 'edit',
|
||||
title: '编辑项目分类',
|
||||
})
|
||||
formData.value = cloneDeep(record)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 确定
|
||||
*/
|
||||
function handleOk() {
|
||||
formRef.value
|
||||
.validateFields()
|
||||
.then(async (values) => {
|
||||
try {
|
||||
showLoading()
|
||||
const params = {
|
||||
...formData.value,
|
||||
}
|
||||
let result = null
|
||||
switch (modal.value.type) {
|
||||
case 'create':
|
||||
result = await apis.projectType.createItem(params).catch(() => {
|
||||
throw new Error()
|
||||
})
|
||||
console.log(result)
|
||||
break
|
||||
case 'edit':
|
||||
result = await apis.projectType.updateItem(params).catch(() => {
|
||||
throw new Error()
|
||||
})
|
||||
break
|
||||
}
|
||||
hideLoading()
|
||||
if (config('http.code.success') === result?.success) {
|
||||
hideModal()
|
||||
emit('ok')
|
||||
}
|
||||
} catch (error) {
|
||||
hideLoading()
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
hideLoading()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消
|
||||
*/
|
||||
function handleCancel() {
|
||||
hideModal()
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭后
|
||||
*/
|
||||
function onAfterClose() {
|
||||
resetForm()
|
||||
hideLoading()
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
handleEdit,
|
||||
handleCreate,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
@ -0,0 +1,241 @@
|
||||
<template>
|
||||
<a-modal :open="modal.open" :title="modal.title" :width="600" :confirm-loading="modal.confirmLoading"
|
||||
:after-close="onAfterClose" :cancel-text="cancelText" @ok="handleOk" @cancel="handleCancel">
|
||||
<a-card>
|
||||
<a-form ref="formRef" :model="formData" :rules="formRules">
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="24">
|
||||
<a-form-item label="类型" name="categoryType">
|
||||
<a-select v-model:value="formData.categoryType" allowClear>
|
||||
<a-select-option v-for="item in dicsStore.dictOptions.PROJECT_TYPE" :key="item.dval"
|
||||
:value="item.dval">{{
|
||||
item.introduction }}</a-select-option>
|
||||
</a-select>
|
||||
<span style="color: #ff4d4f;font-size: 12px;">温馨提示:类型保存后不可修改,请认真选择!</span>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col span="12">
|
||||
<a-form-item label="服务项目分类" name="categoryId">
|
||||
<a-select v-model:value="formData.categoryId" allowClear>
|
||||
<a-select-option v-for="item in categoryList" :key="item.id" :value="item.id">{{
|
||||
item.name }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col span="12">
|
||||
<a-form-item label="服务项目名称" name="name">
|
||||
<a-input v-model:value="formData.name"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col span="12">
|
||||
<a-form-item label="单价" name="price">
|
||||
<a-input-number v-model:value="formData.price" style="width: 100%;">
|
||||
<template #addonAfter>
|
||||
<a-select v-model:value="formData.priceUnit" style="width: 100px">
|
||||
<a-select-option value="次">元/次</a-select-option>
|
||||
<a-select-option value="时">元/时</a-select-option>
|
||||
</a-select>
|
||||
</template>
|
||||
</a-input-number>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col span="12">
|
||||
<a-form-item label="单次服务时长" name="duration">
|
||||
<a-input-number v-model:value="formData.duration" style="width: 100%;">
|
||||
<template #addonAfter>
|
||||
<span>分钟</span>
|
||||
</template>
|
||||
</a-input-number>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col span="12">
|
||||
<a-form-item label="服务频次" name="frequency">
|
||||
<a-input-number v-model:value="formData.frequency" style="width: 100%;">
|
||||
<template #addonAfter>
|
||||
<a-select v-model:value="formData.frequencyUnit" style="width: 80px">
|
||||
<a-select-option value="元/次">元/次</a-select-option>
|
||||
<a-select-option value="元/台">元/台</a-select-option>
|
||||
</a-select>
|
||||
</template>
|
||||
</a-input-number>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col span="12">
|
||||
<a-form-item label="服务形式" name="serviceFormat">
|
||||
<a-select v-model:value="formData.serviceFormat" style="width: 100%;">
|
||||
<a-select-option v-for="item in dicsStore.dictOptions.Service_Format" :key="item.dval"
|
||||
:value="item.dval">{{
|
||||
item.introduction }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="计时标准" name="timeKeeping">
|
||||
<a-input v-model:value="formData.timeKeeping" style="width: 100%;">
|
||||
<template #addonAfter>
|
||||
<a-select v-model:value="formData.timeKeepingUnit" style="width: 120px">
|
||||
<a-select-option value="小时/次">小时/次</a-select-option>
|
||||
<a-select-option value="小时/平方">小时/平方</a-select-option>
|
||||
<a-select-option value="小时/台">小时/台</a-select-option>
|
||||
<a-select-option value="小时/组">小时/组</a-select-option>
|
||||
<a-select-option value="小时/件">小时/件</a-select-option>
|
||||
<a-select-option value="小时/个">小时/个</a-select-option>
|
||||
<a-select-option value="小时/张">小时/张</a-select-option>
|
||||
<a-select-option value="小时/辆">小时/辆</a-select-option>
|
||||
<a-select-option value="小时/项">小时/项</a-select-option>
|
||||
</a-select>
|
||||
</template>
|
||||
</a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="服务内容" name="content">
|
||||
<a-textarea v-model:value="formData.content" placeholder="请输入内容/简介,最多500字" :rows="4" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="封面图片" name="imgList">
|
||||
<gx-upload v-model="formData.imgList" accept-types=".jpg,.png,.webp" :fileNumber="1" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="详情图片" name="detailImgList">
|
||||
<gx-upload v-model="formData.detailImgList" accept-types=".jpg,.png,.webp"
|
||||
:fileNumber="20" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="服务项目视频" name="detailImgList">
|
||||
<a-upload v-model:file-list="fileList"
|
||||
action="https://www.mocky.io/v2/5cc8019d300000980a055e76" accept=".mp4,.3gp,.m3u8">
|
||||
<a-button>
|
||||
<upload-outlined></upload-outlined>
|
||||
上传
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-card>
|
||||
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import GxUpload from '@/components/GxUpload/index.vue'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { ref, defineProps } from 'vue'
|
||||
import { config } from '@/config'
|
||||
import apis from '@/apis'
|
||||
import { useForm, useModal } from '@/hooks'
|
||||
import { useDicsStore } from '@/store'
|
||||
import { message } from 'ant-design-vue'
|
||||
import { UploadOutlined } from '@ant-design/icons-vue';
|
||||
const emit = defineEmits(['ok'])
|
||||
const fileList=ref([])
|
||||
const { modal, showModal, hideModal, showLoading, hideLoading } = useModal()
|
||||
const { formRecord, formData, formRef, formRules, resetForm } = useForm()
|
||||
const cancelText = ref('取消')
|
||||
const dicsStore = useDicsStore()
|
||||
formRules.value = {
|
||||
categoryType: [{ required: true, message: '请选择类型', trigger: ['blur', 'change'] }],
|
||||
categoryId: [{ required: true, message: '请选择类型', trigger: ['blur', 'change'] }],
|
||||
name: [{ required: true, message: '请输入项目分类名称', trigger: 'blur' }],
|
||||
duration:[{ required: true, message: '请输入项目分类名称', trigger: 'blur' }],
|
||||
}
|
||||
const props = defineProps({
|
||||
categoryList: {
|
||||
type: Array,
|
||||
default: []
|
||||
}
|
||||
})
|
||||
/**
|
||||
* 新建
|
||||
*/
|
||||
function handleCreate() {
|
||||
showModal({
|
||||
type: 'create',
|
||||
title: '新增',
|
||||
})
|
||||
formData.value = {
|
||||
priceUnit: '元/次',
|
||||
frequencyUnit: '元/次',
|
||||
timeKeepingUnit: '小时/次'
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 编辑
|
||||
*/
|
||||
function handleEdit(record = {}) {
|
||||
showModal({
|
||||
type: 'edit',
|
||||
title: '编辑',
|
||||
})
|
||||
formRecord.value = record
|
||||
formData.value = cloneDeep(record)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 确定
|
||||
*/
|
||||
function handleOk() {
|
||||
formRef.value
|
||||
.validateFields()
|
||||
.then(async (values) => {
|
||||
try {
|
||||
showLoading()
|
||||
const params = {
|
||||
...formData.value,
|
||||
}
|
||||
let result = null
|
||||
switch (modal.value.type) {
|
||||
case 'create':
|
||||
result = await apis.serviceProject.createItem(params).catch(() => {
|
||||
throw new Error()
|
||||
})
|
||||
console.log(result)
|
||||
break
|
||||
case 'edit':
|
||||
result = await apis.serviceProject.updateItem(params).catch(() => {
|
||||
throw new Error()
|
||||
})
|
||||
break
|
||||
}
|
||||
hideLoading()
|
||||
if (config('http.code.success') === result?.success) {
|
||||
hideModal()
|
||||
emit('ok')
|
||||
}
|
||||
} catch (error) {
|
||||
hideLoading()
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
hideLoading()
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消
|
||||
*/
|
||||
function handleCancel() {
|
||||
hideModal()
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭后
|
||||
*/
|
||||
function onAfterClose() {
|
||||
resetForm()
|
||||
hideLoading()
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
handleEdit,
|
||||
handleCreate,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
@ -0,0 +1,200 @@
|
||||
<template>
|
||||
<a-form :model="searchFormData" labelAlign="left">
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="6">
|
||||
<a-form-item label="类型" name="categoryType">
|
||||
<a-select v-model:value="searchFormData.categoryType" allowClear>
|
||||
<a-select-option v-for="item in dicsStore.dictOptions.PROJECT_TYPE" :key="item.dval"
|
||||
:value="item.dval">{{
|
||||
item.introduction }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<!-- 所在区域 -->
|
||||
<a-col :span="6">
|
||||
<a-form-item label="项目分类" name="categoryId">
|
||||
<a-select v-model:value="searchFormData.categoryId" allowClear>
|
||||
<a-select-option v-for="item in categoryList" :key="item.id" :value="item.name">{{
|
||||
item.name }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<a-form-item label="项目名称" name="name">
|
||||
<a-input v-model:value="searchFormData.name"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<!-- 操作按钮 -->
|
||||
<a-col class="align-left" :span="6">
|
||||
<a-space>
|
||||
<a-button @click="handleResetSearch">{{ $t('button.reset') }}</a-button>
|
||||
<a-button ghost type="primary" @click="handleSearch">
|
||||
{{ $t('button.search') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
<a-card title="服务项目列表">
|
||||
<template #extra>
|
||||
<a-space>
|
||||
<a-button type="primary" @click="$refs.editDialogRef.handleCreate(record)">新建</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
<a-table :columns="columns" :data-source="listData" bordered="true" :loading="loading"
|
||||
:pagination="paginationState" :scroll="{ x: 'max-content' }" @change="onTableChange">
|
||||
<template #bodyCell="{ index, column, record }">
|
||||
<template v-if="column.key === 'serialNumber'">
|
||||
<span>{{ index + 1 }}</span>
|
||||
</template>
|
||||
<template v-if="column.key === 'categoryType'">
|
||||
<span>{{ dicsStore.getDictLabel('PROJECT_TYPE', record.categoryType) }}</span>
|
||||
</template>
|
||||
|
||||
<template v-if="'action' === column.key">
|
||||
<x-action-button @click="$refs.editDialogRef.handleEdit(record)">
|
||||
<span>编辑</span>
|
||||
</x-action-button>
|
||||
<x-action-button @click="handleDelete(record)">
|
||||
<span style="color: #ff4d4f;">删除</span>
|
||||
</x-action-button>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-card>
|
||||
<edit-dialog ref="editDialogRef" @ok="onOk" :categoryList="categoryList"></edit-dialog>
|
||||
|
||||
</template>
|
||||
<script setup>
|
||||
import { message, Modal } from 'ant-design-vue'
|
||||
import { ref } from 'vue'
|
||||
import apis from '@/apis'
|
||||
import { config } from '@/config'
|
||||
import { usePagination } from '@/hooks'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import EditDialog from './projectEditDialog.vue'
|
||||
import { useDicsStore } from '@/store'
|
||||
defineOptions({
|
||||
name: 'serverProject',
|
||||
})
|
||||
const dicsStore = useDicsStore()
|
||||
const categoryList=ref([])
|
||||
const columns = [
|
||||
{ title: '序号', dataIndex: 'serialNumber', key: 'serialNumber', align: 'center', width: 80, },
|
||||
{ title: '类型', dataIndex: 'categoryType', key: 'categoryType', align: 'center', width: 100, },
|
||||
{ title: '分类名称', dataIndex: 'name', key: 'name', align: 'center', width: 180, },
|
||||
{ title: '项目名称', dataIndex: 'name', key: 'name', align: 'center', },
|
||||
{ title: '价格', dataIndex: 'price', key: 'price', align: 'center', },
|
||||
{ title: '简介', dataIndex: 'remark', key: 'remark', align: 'center', },
|
||||
|
||||
{ title: '操作', dataIndex: 'action', key: 'action', align: 'center', width: 120, fixed: 'right', }
|
||||
];
|
||||
const { t } = useI18n() // 解构出t方法
|
||||
const { listData, loading, showLoading, hideLoading, paginationState, resetPagination, searchFormData } = usePagination()
|
||||
const editDialogRef = ref()
|
||||
|
||||
getPageList()
|
||||
getCategoriesAll()
|
||||
async function getCategoriesAll() {
|
||||
try {
|
||||
console.log(111)
|
||||
const { success, data, total } = await apis.projectType
|
||||
.getProjectListAll({
|
||||
pageSize:100, current:1,
|
||||
})
|
||||
.catch(() => {
|
||||
throw new Error()
|
||||
})
|
||||
if (config('http.code.success') === success) {
|
||||
categoryList.value = data.map(item=>({id:item.id,name:item.name}))
|
||||
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
async function getPageList() {
|
||||
try {
|
||||
const { pageSize, current } = paginationState
|
||||
const { success, data, total } = await apis.serviceProject
|
||||
.getProjectList({
|
||||
pageSize, current,
|
||||
...searchFormData.value,
|
||||
})
|
||||
.catch(() => {
|
||||
throw new Error()
|
||||
})
|
||||
|
||||
if (config('http.code.success') === success) {
|
||||
listData.value = data
|
||||
paginationState.total = total
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
function handleDelete({ id }) {
|
||||
Modal.confirm({
|
||||
title: t('pages.system.user.delTip'),
|
||||
content: t('button.confirm'),
|
||||
okText: t('button.confirm'),
|
||||
onOk: () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
; (async () => {
|
||||
try {
|
||||
const { success } = await apis.serviceProject.delItem(id).catch(() => {
|
||||
throw new Error()
|
||||
})
|
||||
if (config('http.code.success') === success) {
|
||||
resolve()
|
||||
message.success(t('component.message.success.delete'))
|
||||
await getPageList()
|
||||
}
|
||||
} catch (error) {
|
||||
reject()
|
||||
}
|
||||
})()
|
||||
})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页
|
||||
*/
|
||||
function onTableChange({ current, pageSize }) {
|
||||
paginationState.current = current
|
||||
paginationState.pageSize = pageSize
|
||||
getPageList()
|
||||
}
|
||||
|
||||
/**
|
||||
* 搜索
|
||||
*/
|
||||
function handleSearch() {
|
||||
resetPagination()
|
||||
getPageList()
|
||||
}
|
||||
/**
|
||||
* 重置
|
||||
*/
|
||||
function handleResetSearch() {
|
||||
searchFormData.value = {}
|
||||
resetPagination()
|
||||
getPageList()
|
||||
}
|
||||
/**
|
||||
* 编辑完成
|
||||
*/
|
||||
async function onOk() {
|
||||
await getPageList()
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
@ -1,98 +1,51 @@
|
||||
<template>
|
||||
<x-search-bar class="mb-8-2">
|
||||
<template #default="{ gutter, colSpan }">
|
||||
<a-form :model="searchFormData" layout="inline" labelAlign="left">
|
||||
<a-row :gutter="[24, 24]">
|
||||
<!-- 所在区域 -->
|
||||
<a-col :span="8">
|
||||
<a-form-item label="所属服务组织" name="station">
|
||||
<node-tree v-model:value="searchFormData.station" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<!-- 姓名 -->
|
||||
<a-col :span="8">
|
||||
<a-form-item label="姓名" name="name">
|
||||
<a-input v-model:value="searchFormData.name" placeholder="请输入姓名" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<!-- 身份证号 -->
|
||||
<a-col :span="8">
|
||||
<a-form-item label="联系电话" name="phone">
|
||||
<a-input v-model:value="searchFormData.phone" placeholder="请输入联系电话" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-form-item label="护理人员类型" name="serviceType">
|
||||
<a-select v-model:value="searchFormData.serviceType" allowClear>
|
||||
<a-select-option v-for="item in dicsStore.dictOptions.STAFF_TYPE" :key="item.dval"
|
||||
:value="item.dval">{{
|
||||
item.introduction }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-form-item label="护理人员状态" name="status">
|
||||
<a-select v-model:value="searchFormData.status" allowClear>
|
||||
<a-select-option v-for="item in dicsStore.dictOptions.STAFF_STATUS" :key="item.dval"
|
||||
:value="item.dval">{{
|
||||
item.introduction }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="8">
|
||||
<a-form-item label="用工形式" name="workType">
|
||||
<a-select v-model:value="searchFormData.workType" allowClear>
|
||||
<a-select-option v-for="item in dicsStore.dictOptions.USE_TYPE" :key="item.dval"
|
||||
:value="item.dval">{{
|
||||
item.introduction }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<!-- 操作按钮 -->
|
||||
<a-col class="align-right" :span="24">
|
||||
<a-space>
|
||||
<a-button @click="handleResetSearch">{{ $t('button.reset') }}</a-button>
|
||||
<a-button ghost type="primary" @click="handleSearch">
|
||||
{{ $t('button.search') }}
|
||||
</a-button>
|
||||
</a-space>
|
||||
<a-card>
|
||||
<a-tabs v-model:activeKey="activeKey">
|
||||
<a-tab-pane key="1" tab="项目分类">
|
||||
<a-row :gutter="8" :wrap="false">
|
||||
<a-col flex="auto">
|
||||
<a-card title="服务项目分类列表">
|
||||
<template #extra>
|
||||
<a-space>
|
||||
<a-button type="primary"
|
||||
@click="$refs.editDialogRef.handleCreate(record)">新建</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
<a-table :columns="columns" :data-source="listData" bordered="true" :loading="loading"
|
||||
:pagination="paginationState" :scroll="{ x: 'max-content' }" @change="onTableChange">
|
||||
<template #bodyCell="{ index, column, record }">
|
||||
<template v-if="column.key === 'serialNumber'">
|
||||
<span>{{ index + 1 }}</span>
|
||||
</template>
|
||||
<template v-if="column.key === 'categoryType'">
|
||||
<span>{{ dicsStore.getDictLabel('PROJECT_TYPE', record.categoryType) }}</span>
|
||||
</template>
|
||||
<template v-if="column.key === 'status'">
|
||||
<a-tag v-if="record.status === 'enabled'" color="green">启用</a-tag>
|
||||
<a-tag v-else>停用</a-tag>
|
||||
</template>
|
||||
<template v-if="'action' === column.key">
|
||||
<x-action-button @click="$refs.editDialogRef.handleEdit(record)">
|
||||
<span>编辑</span>
|
||||
</x-action-button>
|
||||
<x-action-button @click="handleDelete(record)">
|
||||
<span style="color: #ff4d4f;">删除</span>
|
||||
</x-action-button>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</template>
|
||||
</x-search-bar>
|
||||
<a-row :gutter="8" :wrap="false">
|
||||
<a-col flex="auto">
|
||||
<a-card title="服务人员列表">
|
||||
<template #extra>
|
||||
<a-space>
|
||||
<a-button type="primary" @click="$refs.editDialogRef.handleCreate(record)">新建</a-button>
|
||||
<a-button type="primary">导出</a-button>
|
||||
<a-button type="dashed">导出记录</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
<a-table :columns="columns" :data-source="listData" bordered="true" :loading="loading"
|
||||
:pagination="paginationState" :scroll="{ x: 'max-content' }" @change="onTableChange">
|
||||
<template #bodyCell="{ index, column, record }">
|
||||
<template v-if="column.key === 'serialNumber'">
|
||||
<span>{{ index + 1 }}</span>
|
||||
</template>
|
||||
<template v-if="'action' === column.key">
|
||||
<x-action-button @click="$refs.editDialogRef.handleEdit(record)">
|
||||
<span>编辑</span>
|
||||
</x-action-button>
|
||||
<x-action-button @click="handleDelete(record)">
|
||||
<span style="color: #ff4d4f;">删除</span>
|
||||
</x-action-button>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-tab-pane>
|
||||
<a-tab-pane key="2" tab="服务项目">
|
||||
<ServerProject />
|
||||
</a-tab-pane>
|
||||
</a-tabs>
|
||||
|
||||
</a-card>
|
||||
|
||||
<edit-dialog ref="editDialogRef" @ok="onOk"></edit-dialog>
|
||||
<detail ref="detailRef"></detail>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@ -105,14 +58,14 @@ import { useI18n } from 'vue-i18n'
|
||||
import EditDialog from './components/EditDialog.vue'
|
||||
import { useDicsStore } from '@/store'
|
||||
import AreaCascader from '@/components/AreaCascader/index.vue'
|
||||
import detail from './components/detail.vue'
|
||||
import dayjs from 'dayjs'
|
||||
import NodeTree from '@/components/NodeTree/index.vue'
|
||||
import ServerProject from './components/serverProject.vue'
|
||||
defineOptions({
|
||||
name: 'serverProjectManage',
|
||||
})
|
||||
const dicsStore = useDicsStore()
|
||||
|
||||
const activeKey = ref('1')
|
||||
const columns = [
|
||||
{
|
||||
title: '序号',
|
||||
@ -122,157 +75,53 @@ const columns = [
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
title: '类型',
|
||||
dataIndex: 'categoryType',
|
||||
key: 'categoryType',
|
||||
align: 'center',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '性别',
|
||||
dataIndex: 'gender',
|
||||
key: 'gender',
|
||||
align: 'center',
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: '电话',
|
||||
dataIndex: 'phone',
|
||||
key: 'phone',
|
||||
align: 'center',
|
||||
width: 80,
|
||||
},
|
||||
{
|
||||
title: '身份证号',
|
||||
dataIndex: 'idCard',
|
||||
key: 'idCard',
|
||||
title: '分类名称',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
align: 'center',
|
||||
width: 180,
|
||||
},
|
||||
{
|
||||
title: '护理人员类型',
|
||||
dataIndex: 'serviceType',
|
||||
key: 'serviceType',
|
||||
title: '分类描述',
|
||||
dataIndex: 'remark',
|
||||
key: 'remark',
|
||||
align: 'center',
|
||||
width: 120,
|
||||
},
|
||||
{
|
||||
title: '用工形式',
|
||||
dataIndex: 'workType',
|
||||
key: 'workType',
|
||||
align: 'center',
|
||||
width: 120,
|
||||
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'status',
|
||||
key: 'status',
|
||||
align: 'center',
|
||||
width: 120,
|
||||
width: 80,
|
||||
},
|
||||
// --- 联系方式 ---
|
||||
{
|
||||
title: '护理人员类型',
|
||||
dataIndex: 'serviceType',
|
||||
key: 'serviceType',
|
||||
align: 'center',
|
||||
width: 130,
|
||||
},
|
||||
{
|
||||
title: '所属服务组织',
|
||||
dataIndex: 'stationName',
|
||||
key: 'stationName',
|
||||
align: 'center',
|
||||
width: 120,
|
||||
},
|
||||
// {
|
||||
// title: '组织所在区域',
|
||||
// dataIndex: 'areaLabels',
|
||||
// key: 'areaLabels',
|
||||
// align: 'center',
|
||||
// width: 120,
|
||||
// },
|
||||
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'action',
|
||||
key: 'action',
|
||||
align: 'center',
|
||||
width: 180,
|
||||
width: 120,
|
||||
fixed: 'right',
|
||||
}
|
||||
];
|
||||
const { t } = useI18n() // 解构出t方法
|
||||
const { listData, loading, showLoading, hideLoading, paginationState, resetPagination, searchFormData } = usePagination()
|
||||
const editDialogRef = ref()
|
||||
const detailRef = ref()
|
||||
|
||||
const treeData = ref([
|
||||
{
|
||||
title: 'Node1',
|
||||
value: '0-0',
|
||||
key: '0-0',
|
||||
children: [
|
||||
{
|
||||
value: '0-0-1',
|
||||
key: '0-0-1',
|
||||
slots: {
|
||||
title: 'title',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Child Node2',
|
||||
value: '0-0-2',
|
||||
key: '0-0-2',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Node2',
|
||||
value: '0-1',
|
||||
key: '0-1',
|
||||
},
|
||||
]);
|
||||
const options = ref([
|
||||
{
|
||||
value: 'zhejiang',
|
||||
label: 'Zhejiang',
|
||||
children: [
|
||||
{
|
||||
value: 'hangzhou',
|
||||
label: 'Hangzhou',
|
||||
children: [
|
||||
{
|
||||
value: 'xihu',
|
||||
label: 'West Lake',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
value: 'jiangsu',
|
||||
label: 'Jiangsu',
|
||||
children: [
|
||||
{
|
||||
value: 'nanjing',
|
||||
label: 'Nanjing',
|
||||
children: [
|
||||
{
|
||||
value: 'zhonghuamen',
|
||||
label: 'Zhong Hua Men',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},])
|
||||
|
||||
getPageList()
|
||||
|
||||
async function getPageList() {
|
||||
try {
|
||||
const { pageSize, current } = paginationState
|
||||
const { success, data, total } = await apis.serviceStaffList
|
||||
const { success, data, total } = await apis.projectType
|
||||
.getProjectList({
|
||||
pageSize,
|
||||
current: current,
|
||||
@ -290,28 +139,7 @@ async function getPageList() {
|
||||
|
||||
}
|
||||
}
|
||||
/**核销 */
|
||||
const checkHandler = (record) => {
|
||||
Modal.confirm({
|
||||
title: '即将核销是否继续',
|
||||
content: t('button.confirm'),
|
||||
okText: t('button.confirm'),
|
||||
onOk: async () => {
|
||||
const params = {
|
||||
...record,
|
||||
status: 'success'
|
||||
}
|
||||
const { success } = await apis.productOrder.updateItem(params.id, params).catch(() => {
|
||||
// throw new Error()
|
||||
})
|
||||
if (config('http.code.success') === success) {
|
||||
// resolve()
|
||||
message.success('核销成功')
|
||||
await getPageList()
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
@ -324,7 +152,7 @@ function handleDelete({ id }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
; (async () => {
|
||||
try {
|
||||
const { success } = await apis.productOrder.delItem(id).catch(() => {
|
||||
const { success } = await apis.projectType.delItem(id).catch(() => {
|
||||
throw new Error()
|
||||
})
|
||||
if (config('http.code.success') === success) {
|
||||
|
||||
184
src/views/login/bigScreen.vue
Normal file
184
src/views/login/bigScreen.vue
Normal file
@ -0,0 +1,184 @@
|
||||
<template>
|
||||
<div class="screen-container">
|
||||
<div class="container">
|
||||
<div class="screen-title">
|
||||
居家养老服务数据展示
|
||||
</div>
|
||||
<div class="screen-content">
|
||||
<div>
|
||||
<div>
|
||||
<div class="card-title">服务对象人口统计</div>
|
||||
<div class="card-content">
|
||||
<!-- <dv-active-ring-chart :config="config1" style="width:300px;height:300px" /> -->
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import {ref} from 'vue'
|
||||
const config1=ref(
|
||||
{
|
||||
|
||||
radius: '40%',
|
||||
activeRadius: '45%',
|
||||
data: [
|
||||
{
|
||||
name: '周口',
|
||||
value: 55
|
||||
},
|
||||
{
|
||||
name: '南阳',
|
||||
value: 120
|
||||
},
|
||||
{
|
||||
name: '西峡',
|
||||
value: 78
|
||||
},
|
||||
{
|
||||
name: '驻马店',
|
||||
value: 66
|
||||
},
|
||||
{
|
||||
name: '新乡',
|
||||
value: 80
|
||||
}
|
||||
],
|
||||
digitalFlopStyle: {
|
||||
fontSize: 20
|
||||
},
|
||||
showOriginValue: true
|
||||
}
|
||||
)
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.screen-container {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
background-image: url(./../../assets/imgs/screenbg.png);
|
||||
background-size: 100% 100%;
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url(./../../assets/imgs/bg2.png);
|
||||
background-size: 100% 100%;
|
||||
|
||||
.screen-title {
|
||||
font-size: clamp(2rem, 3vw, 3rem);
|
||||
/* 自适应字体大小 */
|
||||
width: 100%;
|
||||
height: 10vh;
|
||||
/* 高度根据内容自动调整 */
|
||||
line-height: 8vh;
|
||||
/* 调整行高以适应不同字体大小 */
|
||||
text-align: center;
|
||||
pointer-events: none;
|
||||
background-size: cover;
|
||||
/* 假设背景图片应该覆盖整个元素 */
|
||||
font-family: ZhenyanG-Flash, sans-serif;
|
||||
/* 添加备用字体 */
|
||||
color: #fff;
|
||||
text-shadow: 0 0 35px rgba(22, 165, 255, .75);
|
||||
}
|
||||
|
||||
.screen-content {
|
||||
height: 90vh;
|
||||
display: flex;
|
||||
gap: 5px;
|
||||
/* 元素之间的间距,推荐现代写法 */
|
||||
padding: 0 15px 15px 15px;
|
||||
box-sizing: border-box;
|
||||
|
||||
/* 第一个子元素:左侧,占 1 份 */
|
||||
&>div:first-child {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
// background: black;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
|
||||
&>div {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
background-color: rgba(69, 117, 147, .2);
|
||||
}
|
||||
}
|
||||
|
||||
/* 第二个子元素:中间,占 2 份 */
|
||||
&>div:nth-child(2) {
|
||||
flex: 2;
|
||||
height: 100%;
|
||||
// background: black;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
|
||||
&>div:first-child {
|
||||
flex: 2;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&>div:last-child {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
background-color: rgba(69, 117, 147, .2);
|
||||
}
|
||||
}
|
||||
|
||||
/* 第三个子元素:右侧,占 1 份 */
|
||||
&>div:last-child {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
// background: black;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
|
||||
&>div {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
background-color: rgba(69, 117, 147, .2);
|
||||
}
|
||||
}
|
||||
|
||||
.card-title {
|
||||
color: #fff;
|
||||
font-size: 1.33333rem;
|
||||
height: 4.16667rem;
|
||||
// margin: 0 24px;
|
||||
line-height: 4.16667rem;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
border-bottom: 1px solid hsla(0, 0%, 60%, .1);
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
width: 2.58333rem;
|
||||
height: 1.91667rem;
|
||||
margin: auto 3px auto 0;
|
||||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAACrRJREFUaEPtWXtwVOUV/53v3r27bHaTyCMQaFARITyqKAaSgApaFakoKC+p8lA0iAGk8rDjtM1M20ExEhEEI5qQAMJAtYjiAI62VkECOFUElacoSANiks1rs3vv/U65u5u4CQm7GybTccb7R7Iz997znd/5nfcl/Mwv+pnrj18A/L8ZjMiApzCzkIDuDDCIdEDqAaW5iepEAgQCQwppnHTotZttWQd2WE/NZE5zGBgjwP1Zgoj4MJHYHKdiZw6RvBQjRAPgKIAUgHUi8gEwA7pfAKDBHVmYxhmnv2qFODMhn3JyZBbzCDdjFhlykGUIAk6S4Be9irJhWVBmq6+IACoLMz9j4AoQXAQoAd3rlW/hbWGaht2oWXWi4zW5r9/b64SvbvYQwxb/mGS6kxiJBBggLJWqWPY88B2ImpojakARAXiKhmQT8/UM3AjgKsByk9B5ZPlM8GqkgWSoMHeZqn1VefuUt0quHE37rrxzmNfhmmU3eFjgaaZtDJmvaMr7i4mqota4qedGerFmzY3JpqmnAfQgg24DkBAAENC8BQABoXQuzle+RWF+hmZ8deRJ5o5VwNwEnaczOAnASTCKTVOszHPS95H0aOl+RAY4B8LTY9DlQopxDJoCUN+mwpplgQGHXltiCOUvW+N7bCsft1AcMvvfKUwtC4JvA8MGpq0kaNEJFbs3EZmtARERQMA98gfaKhyOoYLlDALdzkBig89QiIxm4lpIs5SIiqrsCWuSJ20/mHt6X8dTnQc+QuA5quTOIBwHYyUb4o3cdvRNmwGwBNe8NqSrqfD9DPwOwHXRAADIR5D73VVnVqLzwGIav8mcznybE1hg12Wm5YbMtAssV3yrKVtaw0JUDARY2NhXq65NTDcJUwRjHBjuRoHbgiQC1zm9lYVnErst6nb/jpMLvd7ufk2bJExMISCVgEpmvKRrYulSojOxshA1AEtw9arBnU2bGMugLAL3gZVs6i9qQRQzFKl/qKuOpec6Xf7+B0k3eU/0Gjeo2pW40G5iFAUSAm1hmHmmqpbkEXljARETACsWqhz2G5h5Mhj3AEiOBgATndSMurfb+Wvyaeah/TkeT/vv4+OzEwyeIZg7M3CMGRsli+IlDjrcZgAswRXrhl4GQ94qgMeYcUt4LLT4G5Ca6TuomN4lO68ev3b48BwjW9eHOVg8QoS7ALgA3iclnnVrypYcIiNaEDExUC+0omBoDyI5G4QHAHRoOKyZCl1/gGCzkpiLq9TE/C6TdxzI++Y/iSe7D5ggiZ9SDb4CQDkIeYoqip4l+q5NAZzOH+iMs2tWLDxMQDoArVE5DjNL2E+dmfbEeX9YXcZdNyQ9/q/qx5kzJPDnOF3eDEAhoneJZIFTUXbkENVFA6JVDFiCq17N7C8FJjJhKgHdgsU3eGS40CZNTlmct/xNb7v2L7in7jw4n7lLHTDFrsvJAPqCUXq+71oNKV5+vh1926YALBZcWrtbGfIpEDIbKf1Tq3SBd6mmf49fta8odV/1Tull0zwfDer16x8dXeapTJNIBnqk7RBmrk9VP4qmU201A5ZmlYUZqUyYA9AYAqz+JiAvvFttps04K6S+2eX1vEqPH9774pEj9sM9e860SzxNpuxAwHFJKIIUf3drOJFDVHsxJi4JQFn+wATFro0EaBIYN54PwoRwF2pwn0bBTaaQ+mcub0X+qU7Xrk0Zv8k7i/lmu4lZkPI3ANoBvBugTYDYm6tRSZsB4I3jlDLPd8mqKsYSxDS2ihtgq69plt5BSkLtdshcijQ8mr/6nePJ6a99mDaz5NPkgU63iTuENLMZZCUFDzHtJMEfL7Ypi9oMQL1gz+rM354/dC4YQwA4wqO4BQCw+6u/PNp10Lq30+cXLEjqVzqHubtNl38CMA2AIEYpBO1+zibGtCmA0uLb49px9RgwZoL5BouBgN0v4pxCGnDoNYePdx38+ub0BasWdko9/QRzos2QOQCyLCMwoxKgPbmasGaQFq9LigEuHOaoUowb2OSJRDyawVZrIQJT78UAmEaVw6h571i3wUVvDV7wz2Mde5suYIBi8HyARwWnPhxkYFeupsxoMwDWtKbrxlRBmAii/mwp39zVOIhZmPpBV11ZweHuaWt6j1p/Lps5VTMwjViOJyCFgG8JeEcy78y1qxvbDEBFQfr1JGghg0aRlT1C+ZPIMmDjohZW0CqENLe7fBWv0GOHPrCeymaeoEk8rUhpJYEyyXhXkFxPfvXA4jg63SYAginUcRfATwYGnLACcDEAqun/SldsBaWX9Xk99Z6C0zlVpUnlzk5zVKZ5gllj4HMwL7PZlM2LiH6MVI1bFQPMoKrCjAwWeBCg+wB0uuhBIfMzweuqK9taa0tYGv9wycfzmON0YIRm8KMA3w7AD8YbEiLveY32RlK+adsSzfOBZ8oLhyUK+KYCmA4gFUSBfVGzC6OfSrEOov2u2rK11VpiccL0T8pmMvchYJ5Tl2MYSCDiPcy0WrWJjc8QlUejUMwMWFuKmssz+hnEc4np/mDeD4lpbuPVULzMGgavr3a2fyV54ra9+af3OQ8nDRxpEv9RNfkaAHWC8IqU4jWXhgPRrhxjBmCNldKmjGTgEQAZDVYKbzsvbEelTfqOqYYv70ivm9b0G76i+gn2D7AZylRmTAq54DGA/wabsjGXqCYa68fsQlber4CRLoinATwSQMfmprDwViKUi85oRu0Oh79qBc08unsWs90HTHXrnC3Aqcw4B8J2AbF8sUb7olU+ZgC1RRnddImxILKqZe9g0QrLl03a6PpbqtT3+oV9ZWl8jy1fGHdV7B8xomdlXNx8m0lTCKyeD+BdzFguNWV7HlFZmwBoWKuAJxNoQnCODdtmNTOFBZs5ZqfPs/5cwpWLukzceuAPXNmhznTerTCywDQ4JOFVkuK55+w4GuuiN+oYqC5M62KSbTyCi60062tBAECjhj9oc6sOBLGRSZAn3NVn808lJS1PGf+JN4v5Wjsw16HL0RJwA/iagOVxNlEY7RgZzlBUAALrFM2RzsSW69xxge83MNEYAEmzgone8trcqzo/8N7Ol84edB3q1HeMKnmBYrLVepw7n4Y3CIiixTZ8Gqv1o4oBq2iVrxmaoki+j8EPEdAv0Ko16fEDsRA+EzOg+WsOGIqa+++uUzaMHDnb93t/bTqEfbpgTAAHViklEHjWVJRtsS606lmIyMCPawfHC912vRDyITCsvr+9tU0L2LqFbZwllEHVTl/5dib8VXv0y89ymLX/AlluXWYToRczfgDwppRiSazLrJhcyFOYMQkk0gC2+vJUa/0R/oGjuYxhAVTY+MIQWuFZZ6+1Jdfd6vv8V/dd67U75joMOdr6LsLMu85vM1bpNmXzC0QVsWSe2ACszvwIjD4gxAeHlVBmD/1vtDYJVWLB0rSbtWtPJfVfUnx37wM1tU8MkHa3xeC9gpEcemelYLFssYavW+P7UbuQZ3XmETB6glALhrVsMsMHrjAAAXe0/pA0foBe+3JpyvD8q0cu801nviXexGxFykyLQQZOA/yiy6asi7R1iMRMxBjwFA1ZB+buRPCzyT6IFr+kWN+bAlFBpnnKL73/6DB9/zZLgdBn1rFCcr+ACxIfFSTfdKrqh9H2PC0BiQggkgX+3/d/AfALA5dogf8Bpa+jbRiHVfsAAAAASUVORK5CYII=) no-repeat 50%;
|
||||
background-size: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -172,14 +172,14 @@
|
||||
<!-- 经度 -->
|
||||
<a-col :span="12">
|
||||
<a-form-item label="经度" name="lat">
|
||||
<a-input v-model:value="formData.archive.lat" placeholder="请输入经度" />
|
||||
<a-input-number v-model:value="formData.archive.lat" placeholder="请输入经度" style="width: 100%;"/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<!-- 纬度 -->
|
||||
<a-col :span="12">
|
||||
<a-form-item label="纬度" name="lag">
|
||||
<a-input v-model:value="formData.archive.lag" placeholder="请输入纬度" />
|
||||
<a-input-number v-model:value="formData.archive.lag" placeholder="请输入纬度" style="width: 100%;"/>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<gx-map @handleGetLng="handleGetLng" />
|
||||
@ -578,18 +578,17 @@ function handleOk() {
|
||||
let params = {
|
||||
...formData.value,
|
||||
labels: formData.value.labelsCode ? formData.value.labelsCode.map(item => dicsStore.getDictLabel('Service_Recipient_Category2', item)) : [],
|
||||
birthDate:dayjs(formData.value.birthDate).format('YYYY-MM-DD')
|
||||
|
||||
}
|
||||
params.archive.idCardPhotos = formData.value.archive.idCardPhotos ? formData.value.archive.idCardPhotos.map(item => spliceUrl(item)) : ['']
|
||||
params.archive.uploadedDocuments = formData.value.archive.uploadedDocuments ? formData.value.archive.uploadedDocuments.map(item => spliceUrl(item)) : ['']
|
||||
if(formData.value.governmentPurchasedServiceStartDate.length>0){
|
||||
params.archive.starGovernmentService=dayjs(formData.value.governmentPurchasedServiceStartDate[0]).format('YYYY-MM-DD')
|
||||
params.archive.endGovernmentService=dayjs(formData.value.governmentPurchasedServiceStartDate[1]).format('YYYY-MM-DD')
|
||||
params.archive.idCardPhotos = formData.value.archive.idCardPhotos&&formData.value.archive.idCardPhotos.length>0 ? formData.value.archive.idCardPhotos.map(item => spliceUrl(item)) : ['']
|
||||
params.archive.uploadedDocuments = formData.value.archive.uploadedDocuments&&formData.value.archive.uploadedDocuments.length>0 ? formData.value.archive.uploadedDocuments.map(item => spliceUrl(item)) : ['']
|
||||
if(formData.value.governmentPurchasedServiceStartDate&&formData.value.governmentPurchasedServiceStartDate.length>0){
|
||||
params.archive.starGovernmentService=formData.value.governmentPurchasedServiceStartDate[0]
|
||||
params.archive.endGovernmentService=formData.value.governmentPurchasedServiceStartDate[1]
|
||||
}
|
||||
// 单独封装一个同步校验函数
|
||||
if (params.identityType === '1' && !isValidIdCard(params.identityNo)) {
|
||||
throw new Error('请输入正确的身份证号码');
|
||||
|
||||
return message.error('请输入正确的身份证号码')
|
||||
}
|
||||
let result = null
|
||||
switch (modal.value.type) {
|
||||
@ -607,11 +606,12 @@ function handleOk() {
|
||||
break
|
||||
}
|
||||
hideLoading()
|
||||
if (config('http.code.success') === result?.code) {
|
||||
if (config('http.code.success') === true) {
|
||||
hideModal()
|
||||
emit('ok')
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error.message)
|
||||
hideLoading()
|
||||
// message.error(error.message)
|
||||
}
|
||||
|
||||
318
src/views/serverObj/serverList/components/LineOrder.vue
Normal file
318
src/views/serverObj/serverList/components/LineOrder.vue
Normal file
@ -0,0 +1,318 @@
|
||||
<template>
|
||||
<a-form ref="formRef" :model="formData" :rules="formRules">
|
||||
<a-row :gutter="24">
|
||||
<!-- 姓名 -->
|
||||
<a-col :span="12">
|
||||
<a-form-item label="服务对象" name="name">
|
||||
<a-input v-model:value="formData.name" placeholder="请输入姓名" disabled />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<!-- 性别 -->
|
||||
<a-col :span="12">
|
||||
<a-form-item label="服务站点" name="stationId">
|
||||
<a-select v-model:value="formData.stationId" style="width: 100px; margin-right: 8px;">
|
||||
<a-select-option v-for="item in stationList" :key="item.id" :value="item.id">
|
||||
{{ item.name }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<!-- 出生日期 -->
|
||||
<a-col :span="12">]
|
||||
<a-button @click="ceshi">测试</a-button>
|
||||
<a-form-item label="服务项目" name="serviceItems">
|
||||
<!-- 显示已选项目 -->
|
||||
|
||||
<a-tag v-for="item in selectedServices" :key="item.id" closable @close="handleRemove(item)">
|
||||
{{ item.name }}
|
||||
</a-tag>
|
||||
<a-button @click="showModal2">
|
||||
<PlusOutlined /> 添加服务
|
||||
</a-button>
|
||||
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
</a-row>
|
||||
</a-form>
|
||||
<a-button type="primary" @click="visible3=true">Open Modal</a-button>
|
||||
<a-modal v-model:visible="visible3" title="Basic Modal" :getContainer="() => document.body">
|
||||
<p>Some contents...</p>
|
||||
<p>Some contents...</p>
|
||||
<p>Some contents...</p>
|
||||
</a-modal>
|
||||
<a-modal v-model:open="modalVisible" title="选择服务项目" @ok="handleConfirm" @cancel="handleCancel2" okText="确认"
|
||||
cancelText="取消" :width="600">
|
||||
<a-table :dataSource="serviceList" :columns="columns" :row-selection="rowSelection" :pagination="false"
|
||||
:loading="loading" size="small">
|
||||
<template #bodyCell="{ index, column, record }">
|
||||
<template v-if="column.key === 'categoryType'">
|
||||
<span>{{ dicsStore.getDictLabel('PROJECT_TYPE', record.categoryType) }}</span>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { ref, defineProps,defineExpose } from 'vue'
|
||||
import { config } from '@/config'
|
||||
import apis from '@/apis'
|
||||
import { useForm, useModal } from '@/hooks'
|
||||
import { useDicsStore } from '@/store'
|
||||
import AreaCascader from '@/components/AreaCascader/index.vue'
|
||||
import { validatePhone, validateEmail, validateIdCard } from '@/utils/validate'
|
||||
import { getBirthDate, spliceUrl } from '@/utils/util'
|
||||
import dayjs from 'dayjs'
|
||||
import { PlusOutlined } from '@ant-design/icons-vue'
|
||||
import { message } from 'ant-design-vue'
|
||||
const emit = defineEmits(['ok'])
|
||||
const activeKey = ref('1')
|
||||
const { modal, showModal, hideModal, showLoading, hideLoading } = useModal()
|
||||
const { formRecord, formData, formRef, formRules, resetForm } = useForm()
|
||||
const cancelText = ref('取消')
|
||||
const stationList = ref([])
|
||||
const visible3=ref(false)
|
||||
const props = defineProps({
|
||||
serviceName: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
formRules.value = {
|
||||
name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
|
||||
identityType: [{ required: true, message: '请选择证件类型', trigger: 'change' }],
|
||||
identityNo: [{ required: true, message: '请输入证件号码', trigger: 'blur' }],
|
||||
contact1: [{ validator: validatePhone, trigger: ['blur', 'input'] }, { required: true, message: '请输入联系方式', trigger: 'blur' }],
|
||||
archive: {
|
||||
healthStatus: [{ required: true, message: '请选择健康状况', trigger: 'change' }],
|
||||
serviceStatus: [{ required: true, message: '请选择服务状态', trigger: 'change' }],
|
||||
homeAreaCodes: [{ required: true, message: '请选择并输入家庭地址', trigger: 'change' }],
|
||||
homeDetailAddress: [{ required: true, message: '请输入详细地址', trigger: 'change' }],
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
const dicsStore = useDicsStore()
|
||||
// 已选中的服务项目(用于显示)
|
||||
const selectedServices = ref([])
|
||||
|
||||
// 模态框控制
|
||||
const modalVisible = ref(false)
|
||||
const loading = ref(false)
|
||||
|
||||
// 服务项目列表(来自接口)
|
||||
const serviceList = ref([])
|
||||
|
||||
// 表格列定义
|
||||
const columns = [
|
||||
{ title: '类型', dataIndex: 'categoryType', key: 'categoryType', align: 'center', width: 100, },
|
||||
{ title: '分类名称', dataIndex: 'name', key: 'name', align: 'center', width: 180, },
|
||||
{ title: '项目名称', dataIndex: 'name', key: 'name', align: 'center', },
|
||||
{ title: '价格', dataIndex: 'price', key: 'price', align: 'center', },
|
||||
{ title: '简介', dataIndex: 'remark', key: 'remark', align: 'center', },
|
||||
]
|
||||
// 模拟接口请求(替换为真实 API)
|
||||
async function fetchServices(){
|
||||
try {
|
||||
const { pageSize, current } = paginationState
|
||||
const { success, data, total } = await apis.serviceProject
|
||||
.getProjectList({
|
||||
pageSize, current,
|
||||
...searchFormData.value,
|
||||
})
|
||||
.catch(() => {
|
||||
throw new Error()
|
||||
})
|
||||
|
||||
if (config('http.code.success') === success) {
|
||||
listData.value = data
|
||||
paginationState.total = total
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 表格行选择配置
|
||||
const rowSelection = {
|
||||
type: 'checkbox',
|
||||
selectedRowKeys: ref([]),
|
||||
onChange: (selectedRowKeys, selectedRows) => {
|
||||
rowSelection.selectedRowKeys.value = selectedRowKeys
|
||||
},
|
||||
getCheckboxProps: (record) => ({
|
||||
disabled: false
|
||||
})
|
||||
}
|
||||
|
||||
// 打开模态框
|
||||
function ceshi(){
|
||||
console.log(111)
|
||||
modalVisible.value = true
|
||||
// 第一次加载数据
|
||||
if (serviceList.value.length === 0) {
|
||||
fetchServices()
|
||||
}
|
||||
// 恢复已选中状态
|
||||
const selectedIds = selectedServices.value.map(s => s.id)
|
||||
rowSelection.selectedRowKeys.value = selectedIds
|
||||
}
|
||||
|
||||
// 移除已选项目
|
||||
const handleRemove = (item) => {
|
||||
selectedServices.value = selectedServices.value.filter(s => s.id !== item.id)
|
||||
// 同步到 form(可选)
|
||||
form.serviceItems = selectedServices.value.map(s => s.id)
|
||||
}
|
||||
|
||||
// 确认选择
|
||||
const handleConfirm = () => {
|
||||
const selectedRows = serviceList.value.filter(item =>
|
||||
rowSelection.selectedRowKeys.value.includes(item.id)
|
||||
)
|
||||
selectedServices.value = selectedRows
|
||||
// 同步到 form 字段(可用于表单提交)
|
||||
form.serviceItems = selectedRows.map(s => s.id)
|
||||
modalVisible.value = false
|
||||
}
|
||||
|
||||
// 取消
|
||||
const handleCancel2 = () => {
|
||||
modalVisible.value = false
|
||||
}
|
||||
/**
|
||||
* 编辑
|
||||
*/
|
||||
handleEdit()
|
||||
async function handleEdit(record = {}) {
|
||||
formData.value.name = record.name
|
||||
try {
|
||||
showLoading()
|
||||
const { data, success } = await apis.serviceMenu.getServiceSiteList({ pageSize: 100, current: 1 })
|
||||
if (!success) {
|
||||
hideModal()
|
||||
return
|
||||
}
|
||||
stationList.value = data.map(item => ({ id: item.id, name: item.name }))
|
||||
} catch (error) {
|
||||
hideModal()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 确定
|
||||
*/
|
||||
function handleOk() {
|
||||
formRef.value
|
||||
.validateFields()
|
||||
.then(async (values) => {
|
||||
try {
|
||||
showLoading()
|
||||
let params = {
|
||||
...formData.value,
|
||||
labels: formData.value.labelsCode ? formData.value.labelsCode.map(item => dicsStore.getDictLabel('Service_Recipient_Category2', item)) : [],
|
||||
birthDate: dayjs(formData.value.birthDate).format('YYYY-MM-DD')
|
||||
}
|
||||
params.archive.idCardPhotos = formData.value.archive.idCardPhotos.length > 0 ? formData.value.archive.idCardPhotos.map(item => spliceUrl(item)) : ['']
|
||||
params.archive.uploadedDocuments = formData.value.archive.uploadedDocuments.length > 0 ? formData.value.archive.uploadedDocuments.map(item => spliceUrl(item)) : ['']
|
||||
if (formData.value.governmentPurchasedServiceStartDate.length > 0) {
|
||||
params.archive.starGovernmentService = dayjs(formData.value.governmentPurchasedServiceStartDate[0]).format('YYYY-MM-DD')
|
||||
params.archive.endGovernmentService = dayjs(formData.value.governmentPurchasedServiceStartDate[1]).format('YYYY-MM-DD')
|
||||
}
|
||||
// 单独封装一个同步校验函数
|
||||
if (params.identityType === '1' && !isValidIdCard(params.identityNo)) {
|
||||
return message.error('请输入正确的身份证号码')
|
||||
}
|
||||
let result = null
|
||||
switch (modal.value.type) {
|
||||
case 'create':
|
||||
result = await apis.serverObj.createItem(params).catch(() => {
|
||||
throw new Error()
|
||||
})
|
||||
console.log('result', result.code)
|
||||
break
|
||||
case 'edit':
|
||||
console.log(params)
|
||||
result = await apis.serverObj.updateItem(params.id, params).catch(() => {
|
||||
throw new Error()
|
||||
})
|
||||
break
|
||||
}
|
||||
hideLoading()
|
||||
if (config('http.code.success') === result?.code) {
|
||||
hideModal()
|
||||
emit('ok')
|
||||
}
|
||||
} catch (error) {
|
||||
hideLoading()
|
||||
// message.error(error.message)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
hideLoading()
|
||||
})
|
||||
}
|
||||
// 提取出生日期方法
|
||||
const extractBirthDateFromIdCard = () => {
|
||||
console.log(111)
|
||||
const { identityNo } = formData.value;
|
||||
if (!identityNo) {
|
||||
formData.value.birthDate = '';
|
||||
return;
|
||||
}
|
||||
console.log(getBirthDate(identityNo))
|
||||
formData.value.birthDate = dayjs(getBirthDate(identityNo));
|
||||
};
|
||||
function onAreaChange(value, labels) {
|
||||
|
||||
formData.value.archive.homeAreaLabels = [...labels]
|
||||
}
|
||||
function onAreaHoldChange(value, labels) {
|
||||
|
||||
formData.value.archive.houseAreaLabels = [...labels]
|
||||
}
|
||||
function handleGetLng(obj) {
|
||||
formData.value.lat = obj.lat
|
||||
formData.value.lag = obj.lng
|
||||
}
|
||||
// 修复自定义上传方法
|
||||
const handleCustomRequest = async (options) => {
|
||||
const { file, onProgress, onSuccess, onError } = options;
|
||||
|
||||
try {
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
const { data } = await apis.common.uploadFile(formData);
|
||||
const fullUrl = config('http.apiBasic') + data;
|
||||
console.log(fullUrl)
|
||||
} catch (err) {
|
||||
message.error('上传失败');
|
||||
}
|
||||
};
|
||||
/**
|
||||
* 取消
|
||||
*/
|
||||
function handleCancel() {
|
||||
hideModal()
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭后
|
||||
*/
|
||||
function onAfterClose() {
|
||||
resetForm()
|
||||
formData.value.archive = {}
|
||||
hideLoading()
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
handleCreate,
|
||||
handleEdit,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
396
src/views/serverObj/serverList/components/LineOrder2.vue
Normal file
396
src/views/serverObj/serverList/components/LineOrder2.vue
Normal file
@ -0,0 +1,396 @@
|
||||
<template>
|
||||
<a-modal :open="modal.open" :title="modal.title" :width="800" :confirm-loading="modal.confirmLoading"
|
||||
:after-close="onAfterClose" :cancel-text="cancelText" @ok="handleOk" @cancel="handleCancel">
|
||||
<a-card>
|
||||
<a-form ref="formRef" :model="formData" :rules="formRules">
|
||||
<a-row :gutter="24">
|
||||
<!-- 姓名 -->
|
||||
<a-col :span="12">
|
||||
<a-form-item label="服务对象" name="name">
|
||||
<a-input v-model:value="formData.name" placeholder="请输入姓名" disabled />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<!-- 性别 -->
|
||||
<a-col :span="12">
|
||||
<a-form-item label="服务站点" name="stationId">
|
||||
<a-select v-model:value="formData.stationId">
|
||||
<a-select-option v-for="item in stationList" :key="item.id" :value="item.id">
|
||||
{{ item.name }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<!-- 出生日期 -->
|
||||
<a-col :span="24">
|
||||
<div style="margin-bottom: 20px;">
|
||||
<span style="margin-right: 10px;"><span style="color: red;">*</span> 服务项目:</span>
|
||||
<!-- 显示已选项目 -->
|
||||
<a-tag v-for="item in selectedServices" :key="item.id" closable @close="handleRemove(item)">
|
||||
{{ item.name }}
|
||||
</a-tag>
|
||||
<a-tag @click="showModal2" color="#108ee9" style="cursor: pointer;">
|
||||
添加服务
|
||||
</a-tag>
|
||||
</div>
|
||||
|
||||
</a-col>
|
||||
|
||||
<a-col :span="12">
|
||||
<a-form-item label="服务费用" name="price">
|
||||
<a-input-number v-model:value="formData.price" style="width: 100%;"></a-input-number>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<template v-if="formData.orderType == '2'">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="服务人员" name="servicePersonId">
|
||||
<a-select v-model:value="formData.servicePersonId">
|
||||
<a-select-option v-for="item in servicePersonList" :key="item.id" :value="item.id">
|
||||
{{ item.name }}
|
||||
</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="计划日期" name="planeDate">
|
||||
<a-range-picker v-model:value="formData.planeDate" placeholder="请选择计划日期" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="计划开始时间" name="plannedStartDate">
|
||||
<a-time-picker v-model:value="formData.plannedStartDate" format="HH:mm"
|
||||
style="width: 100%;" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="要求工单时长" name="workDuration">
|
||||
<a-input-number v-model:value="formData.workDuration">
|
||||
<template #addonAfter>分钟</template>
|
||||
</a-input-number>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="服务地址(如修改服务地址,请务必更新地图定位地址)" name="areaCodes">
|
||||
<AreaCascader v-model:value="formData.areaCodes" @change="onAreaChange" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="详细地址" name="detailAddress">
|
||||
<a-input v-model:value="formData.detailAddress"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="地理地图定位" name="gps">
|
||||
<div @click="mapVisible = true">
|
||||
<span>{{ gps }}</span>
|
||||
<AimOutlined style="color: #40a9ff;" />
|
||||
</div>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</template>
|
||||
|
||||
<a-col :span="24">
|
||||
<a-form-item label="服务内容" name="content">
|
||||
<a-input v-model:value="formData.content"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-card>
|
||||
</a-modal>
|
||||
<a-modal v-model:open="modalVisible" title="选择服务项目" @ok="handleConfirm" @cancel="handleCancel2" okText="确认"
|
||||
cancelText="取消" :width="600">
|
||||
<a-table :dataSource="serviceList" :columns="columns" :row-key="record => record.id"
|
||||
:row-selection="rowSelection" :pagination="false" :loading="loading" size="small">
|
||||
<template #bodyCell="{ index, column, record }">
|
||||
<template v-if="column.key === 'categoryType'">
|
||||
<span>{{ dicsStore.getDictLabel('PROJECT_TYPE', record.categoryType) }}</span>
|
||||
</template>
|
||||
</template>
|
||||
</a-table>
|
||||
</a-modal>
|
||||
<a-modal v-model:open="mapVisible" title="选择地址" @ok="mapVisible = false" @cancel="mapVisible = false" okText="确认"
|
||||
cancelText="取消" :width="600">
|
||||
<gx-map @handleGetLng="handleGetLng" />
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { ref, computed } from 'vue'
|
||||
import { config } from '@/config'
|
||||
import apis from '@/apis'
|
||||
import { useForm, useModal, usePagination } from '@/hooks'
|
||||
import { useDicsStore } from '@/store'
|
||||
import AreaCascader from '@/components/AreaCascader/index.vue'
|
||||
import { validatePhone, validateEmail, validateIdCard } from '@/utils/validate'
|
||||
import { getBirthDate, spliceUrl } from '@/utils/util'
|
||||
import dayjs from 'dayjs'
|
||||
import { message } from 'ant-design-vue'
|
||||
import { selectProps } from 'ant-design-vue/es/vc-select'
|
||||
import { AimOutlined } from '@ant-design/icons-vue'
|
||||
import GxMap from '@/components/GxMap/index.vue'
|
||||
const emit = defineEmits(['ok'])
|
||||
const activeKey = ref('1')
|
||||
const { modal, showModal, hideModal, showLoading, hideLoading } = useModal()
|
||||
const { formRecord, formData, formRef, formRules, resetForm } = useForm()
|
||||
const { paginationState } = usePagination()
|
||||
const cancelText = ref('取消')
|
||||
const servicePersonList = ref([])
|
||||
const gps = ref('')
|
||||
const mapVisible = ref(false)
|
||||
const stationList = ref([])
|
||||
formRules.value = {
|
||||
name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
|
||||
identityType: [{ required: true, message: '请选择证件类型', trigger: 'change' }],
|
||||
identityNo: [{ required: true, message: '请输入证件号码', trigger: 'blur' }],
|
||||
contact1: [{ validator: validatePhone, trigger: ['blur', 'input'] }, { required: true, message: '请输入联系方式', trigger: 'blur' }],
|
||||
planeDate: [{ required: true, message: '请选择计划日期', trigger: ['blur', 'input'] }],
|
||||
servicePersonId: [{ required: true, message: '请选择服务人员', trigger: ['blur', 'input'] }],
|
||||
plannedStartDate: [{ required: true, message: '请选择计划开始时间', trigger: ['blur', 'input'] }],
|
||||
workDuration: [{ required: true, message: '请选择计划日期', trigger: ['blur', 'input'] }],
|
||||
areaCodes: [{ required: true, message: '请选择服务地址', trigger: ['blur', 'input'] }],
|
||||
detailAddress: [{ required: true, message: '请输入详细地址', trigger: 'blur' }]
|
||||
}
|
||||
|
||||
const dicsStore = useDicsStore()
|
||||
// 已选中的服务项目(用于显示)
|
||||
const selectedServices = ref([])
|
||||
|
||||
// 模态框控制
|
||||
const modalVisible = ref(false)
|
||||
const loading = ref(false)
|
||||
|
||||
// 服务项目列表(来自接口)
|
||||
const serviceList = ref([])
|
||||
|
||||
// 表格列定义
|
||||
const columns = [
|
||||
{ title: '类型', dataIndex: 'categoryType', key: 'categoryType', align: 'center', width: 100, },
|
||||
{ title: '分类名称', dataIndex: 'name', key: 'name', align: 'center', width: 180, },
|
||||
{ title: '项目名称', dataIndex: 'name', key: 'name', align: 'center', },
|
||||
{ title: '价格', dataIndex: 'price', key: 'price', align: 'center', },
|
||||
{ title: '简介', dataIndex: 'remark', key: 'remark', align: 'center', },
|
||||
]
|
||||
// 1. 定义 selectedRowKeys 为普通 ref(只用于存储值)
|
||||
const selectedRowKeys = ref([])
|
||||
const rowSelection = computed(() => ({
|
||||
selectedRowKeys: selectedRowKeys.value,
|
||||
onChange: (newSelectedRowKeys, selectedRows) => {
|
||||
console.log('selectedRowKeys:', newSelectedRowKeys, 'selectedRows:', selectedRows)
|
||||
selectedRowKeys.value = newSelectedRowKeys
|
||||
selectedServices.value = selectedRows
|
||||
formData.value.price = selectedServices.value.reduce((sum, item) => sum + item.price, 0)
|
||||
},
|
||||
getCheckboxProps: (record) => ({
|
||||
disabled: record.name === 'Disabled User',
|
||||
name: record.name,
|
||||
}),
|
||||
}))
|
||||
getSeveicePeople()
|
||||
async function getSeveicePeople() {
|
||||
try {
|
||||
const { success, data, total } = await apis.serviceStaffList
|
||||
.getProjectList({
|
||||
pageSize: 100,
|
||||
current: 1,
|
||||
})
|
||||
.catch(() => {
|
||||
throw new Error()
|
||||
})
|
||||
|
||||
if (config('http.code.success') === success) {
|
||||
servicePersonList.value = data.map(item => ({ id: item.id, name: item.name }))
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
}
|
||||
function onAreaChange(value, labels) {
|
||||
formData.value.areaLabels = [...labels]
|
||||
}
|
||||
function handleGetLng(obj) {
|
||||
gps.value = obj.address
|
||||
formData.value.lat = obj.lat
|
||||
formData.value.lng = obj.lng
|
||||
}
|
||||
// 打开模态框
|
||||
async function showModal2() {
|
||||
modalVisible.value = true
|
||||
// 第一次加载数据
|
||||
// if (serviceList.value.length === 0) {
|
||||
// fetchServices()
|
||||
// }
|
||||
// 恢复已选中状态
|
||||
|
||||
try {
|
||||
const { pageSize, current } = paginationState
|
||||
const { success, data, total } = await apis.serviceProject
|
||||
.getProjectList({
|
||||
pageSize, current,
|
||||
})
|
||||
.catch(() => {
|
||||
throw new Error()
|
||||
})
|
||||
|
||||
if (config('http.code.success') === success) {
|
||||
serviceList.value = data
|
||||
paginationState.total = total
|
||||
if (selectedServices.value.length > 0) {
|
||||
const selectedIds = selectedServices.value.map(s => s.id)
|
||||
selectedRowKeys.value = selectedIds
|
||||
} else {
|
||||
selectedRowKeys.value = []
|
||||
}
|
||||
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// 移除已选项目
|
||||
const handleRemove = (item) => {
|
||||
selectedServices.value = selectedServices.value.filter(s => s.id !== item.id)
|
||||
formData.value.price = selectedServices.value.reduce((sum, item) => sum + item.price, 0)
|
||||
}
|
||||
|
||||
// 确认选择
|
||||
const handleConfirm = () => {
|
||||
modalVisible.value = false
|
||||
}
|
||||
|
||||
// 取消
|
||||
const handleCancel2 = () => {
|
||||
modalVisible.value = false
|
||||
}
|
||||
/**
|
||||
* 新建
|
||||
*/
|
||||
function handleCreate() {
|
||||
formData.value.gender = '1'
|
||||
showModal({
|
||||
type: 'create',
|
||||
title: '新建项',
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
*/
|
||||
async function handleEdit(record = {}, type) {
|
||||
showModal({
|
||||
type: 'edit',
|
||||
title: '编辑对象'
|
||||
})
|
||||
formData.value.orderType = type, //线下2 线上1]
|
||||
formData.value.customerId = record.id
|
||||
formData.value.name = record.name
|
||||
formData.value.areaCodes = record.archive.homeAreaCodes
|
||||
formData.value.areaLabels = record.archive.homeAreaLabels
|
||||
if (type == '2') {
|
||||
|
||||
formData.value.detailAddress = record.archive.homeDetailAddress
|
||||
gps.value = record.region.join('') + record.archive.homeDetailAddress
|
||||
formData.value.lat = record.archive.lag
|
||||
formData.value.lng = record.archive.lat
|
||||
}
|
||||
|
||||
getServiceStation()
|
||||
}
|
||||
async function getServiceStation() {
|
||||
try {
|
||||
showLoading()
|
||||
const { success, data, total } = await apis.serviceMenu
|
||||
.getServiceSiteList({
|
||||
pageSize: 100,
|
||||
current: 1,
|
||||
})
|
||||
.catch(() => {
|
||||
throw new Error()
|
||||
})
|
||||
hideLoading()
|
||||
if (config('http.code.success') === success) {
|
||||
stationList.value = data.map(item => ({ id: item.id, name: item.name }))
|
||||
}
|
||||
} catch (error) {
|
||||
hideLoading()
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 确定
|
||||
*/
|
||||
function handleOk() {
|
||||
if (!selectedServices.value.length) {
|
||||
return message.error('请选择服务项目')
|
||||
}
|
||||
formRef.value
|
||||
.validateFields()
|
||||
.then(async (values) => {
|
||||
try {
|
||||
showLoading()
|
||||
|
||||
let params = {
|
||||
...formData.value,
|
||||
|
||||
orderingMethod: 'pc'
|
||||
}
|
||||
if (formData.value.planeDate && formData.value.planeDate.length > 0) {
|
||||
params.plannedServiceStartDate = formData.value.planeDate[0]
|
||||
params.plannedEndDate = formData.value.planeDate[1]
|
||||
}
|
||||
params.projects = serviceList.value
|
||||
let result = null
|
||||
switch (modal.value.type) {
|
||||
case 'create':
|
||||
result = await apis.serverObj.createItem(params).catch(() => {
|
||||
throw new Error()
|
||||
})
|
||||
console.log('result', result.code)
|
||||
break
|
||||
case 'edit':
|
||||
console.log(params)
|
||||
result = await apis.serverObj.createOrderItem(params).catch(() => {
|
||||
throw new Error()
|
||||
})
|
||||
break
|
||||
}
|
||||
hideLoading()
|
||||
if (config('http.code.success') === true) {
|
||||
hideModal()
|
||||
emit('ok')
|
||||
}
|
||||
} catch (error) {
|
||||
hideLoading()
|
||||
// message.error(error.message)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
hideLoading()
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 取消
|
||||
*/
|
||||
function handleCancel() {
|
||||
selectedServices.value = []
|
||||
hideModal()
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭后
|
||||
*/
|
||||
function onAfterClose() {
|
||||
selectedServices.value = []
|
||||
resetForm()
|
||||
hideLoading()
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
handleCreate,
|
||||
handleEdit,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
@ -291,6 +291,9 @@
|
||||
</template>
|
||||
<template v-if="column.key === 'governmentPurchasedService'">
|
||||
<span>{{ record.governmentPurchasedService ? '是' : '' }}</span>
|
||||
</template>
|
||||
<template v-if="column.key === 'region'">
|
||||
<span>{{ record.region&&record.region.join('/')}}</span>
|
||||
</template>
|
||||
<template v-if="column.key === 'serviceRecipientCategory'">
|
||||
<span>{{
|
||||
@ -302,13 +305,13 @@
|
||||
<x-action-button @click="$refs.detailRef.handleCreate(record)">
|
||||
<span>详情</span>
|
||||
</x-action-button>
|
||||
<x-action-button @click="checkHandler(record)">
|
||||
<x-action-button @click="$refs.lineOrderRef.handleEdit(record,'2')">
|
||||
<span>线下工单</span>
|
||||
</x-action-button>
|
||||
<x-action-button @click="$refs.editDialogRef.handleEdit(record)">
|
||||
<span>编辑</span>
|
||||
</x-action-button>
|
||||
<x-action-button @click="checkHandler(record)">
|
||||
<x-action-button @click="$refs.lineOrderRef.handleEdit(record,'1')">
|
||||
<span>线上工单</span>
|
||||
</x-action-button>
|
||||
<x-action-button @click="checkHandler(record)">
|
||||
@ -322,11 +325,16 @@
|
||||
</a-row>
|
||||
<edit-dialog ref="editDialogRef" @ok="onOk"></edit-dialog>
|
||||
<detail ref="detailRef"></detail>
|
||||
<LineOrder2 ref="lineOrderRef" />
|
||||
|
||||
<!-- <a-drawer v-model:open="lineOpen" class="custom-class" width="600" root-class-name="root-class-name" :root-style="{ color: 'blue' }" :title="lineTitle" placement="right">
|
||||
<LineOrder ref="lineOrderRef" />
|
||||
</a-drawer> -->
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { message, Modal } from 'ant-design-vue'
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { nextTick, onMounted, ref } from 'vue'
|
||||
import apis from '@/apis'
|
||||
import { config } from '@/config'
|
||||
import { usePagination } from '@/hooks'
|
||||
@ -334,6 +342,8 @@ import { useI18n } from 'vue-i18n'
|
||||
import totalImg from '@/assets/imgs/total.png'
|
||||
import EditDialog from './components/EditDialog.vue'
|
||||
import detail from './components/detail.vue'
|
||||
import LineOrder from './components/LineOrder.vue'
|
||||
import LineOrder2 from './components/LineOrder2.vue'
|
||||
import { useDicsStore } from '@/store'
|
||||
import AreaCascader from '@/components/AreaCascader/index.vue'
|
||||
import NodeTree from '@/components/NodeTree/index.vue'
|
||||
@ -343,7 +353,9 @@ defineOptions({
|
||||
})
|
||||
const totalCount = ref(0) // 总人数
|
||||
const dicsStore = useDicsStore()
|
||||
|
||||
const lineOpen = ref(false)
|
||||
const lineTitle = ref('线下工单')
|
||||
const serviceName = ref('')
|
||||
const columns = [
|
||||
{
|
||||
title: '序号',
|
||||
@ -495,7 +507,8 @@ const columns = [
|
||||
dataIndex: 'region',
|
||||
key: 'region',
|
||||
align: 'center',
|
||||
width: 120,
|
||||
width: 180,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: '详细地址',
|
||||
@ -503,6 +516,7 @@ const columns = [
|
||||
key: 'detailedAddress',
|
||||
align: 'center',
|
||||
width: 200,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: '残疾类型',
|
||||
@ -563,7 +577,7 @@ const { t } = useI18n() // 解构出t方法
|
||||
const { listData, loading, showLoading, hideLoading, paginationState, resetPagination, searchFormData } = usePagination()
|
||||
const editDialogRef = ref()
|
||||
const detailRef = ref()
|
||||
|
||||
const lineOrderRef = ref()
|
||||
|
||||
onMounted(() => {
|
||||
searchFormData.value.serviceNodeIds = dicsStore.orgTree[0].value
|
||||
@ -693,7 +707,11 @@ function handleResetSearch() {
|
||||
async function onOk() {
|
||||
await getPageList()
|
||||
}
|
||||
function lineOrder(record) {
|
||||
lineOpen.value = true;
|
||||
lineTitle.value = '线下工单';
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
|
||||
@ -1,14 +1,34 @@
|
||||
<template>
|
||||
<a-modal :open="modal.open" :title="modal.title" :width="600" :confirm-loading="modal.confirmLoading"
|
||||
<a-modal :open="modal.open" :title="modal.title" :width="800" :confirm-loading="modal.confirmLoading"
|
||||
:after-close="onAfterClose" :cancel-text="cancelText" @ok="handleOk" @cancel="handleCancel">
|
||||
<a-card>
|
||||
<a-form ref="formRef" :model="formData" :rules="formRules">
|
||||
<a-row :gutter="24">
|
||||
<a-col :span="12">
|
||||
<a-form-item label="姓名" name="name">
|
||||
<a-form-item label="所属服务站点" name="stationId">
|
||||
<a-select v-model:value="formData.stationId" allowClear>
|
||||
<a-select-option v-for="item in stationList" :key="item.id"
|
||||
:value="item.id">{{
|
||||
item.name }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="服务人员姓名" name="name">
|
||||
<a-input v-model:value="formData.name" placeholder="请输入姓名" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="身份证号" name="idCard">
|
||||
<a-input v-model:value="formData.idCard" placeholder="请输入证件号码"
|
||||
@change="extractBirthDateFromIdCard" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="出生日期" name="birthDate2">
|
||||
<a-input v-model:value="formData.birthDate2" placeholder="根据身份证号码自动识别" disabled />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<!-- 性别 -->
|
||||
<a-col :span="12">
|
||||
<a-form-item label="性别" name="gender">
|
||||
@ -19,21 +39,13 @@
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<!-- 证件号码 -->
|
||||
<a-col :span="12">
|
||||
<a-form-item label="身份证号" name="idCard">
|
||||
<a-input v-model:value="formData.idCard" placeholder="请输入证件号码" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="电话" name="phone">
|
||||
<a-input v-model:value="formData.phone" placeholder="请输入电话" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="12">
|
||||
<a-form-item label="电话" name="phone">
|
||||
<a-input v-model:value="formData.phone" placeholder="请输入电话" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
<a-col :span="12">
|
||||
<a-form-item label="护理人员类型" name="serviceType">
|
||||
<a-select v-model:value="formData.serviceType" allowClear>
|
||||
@ -44,9 +56,32 @@
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="护理人员状态" name="status">
|
||||
<a-select v-model:value="formData.status" allowClear>
|
||||
<a-select-option v-for="item in dicsStore.dictOptions.STAFF_STATUS" :key="item.dval"
|
||||
<a-form-item label="资格证照名称" name="qualificationName">
|
||||
<a-input v-model:value="formData.qualificationName" placeholder="请输入资格证照名称" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="资格证照等级" name="qualificationLV">
|
||||
<a-select v-model:value="formData.qualificationLV" allowClear>
|
||||
<a-select-option v-for="item in dicsStore.dictOptions.QUA_LV" :key="item.dval"
|
||||
:value="item.dval">{{
|
||||
item.introduction }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="参保情况" name="insuranceStatus">
|
||||
<a-select v-model:value="formData.insuranceStatus" allowClear>
|
||||
<a-select-option v-for="item in dicsStore.dictOptions.INSURANCE_STATUS" :key="item.dval"
|
||||
:value="item.dval">{{
|
||||
item.introduction }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="学历" name="education">
|
||||
<a-select v-model:value="formData.education" allowClear>
|
||||
<a-select-option v-for="item in dicsStore.dictOptions.EDUCATION_LEVEL" :key="item.dval"
|
||||
:value="item.dval">{{
|
||||
item.introduction }}</a-select-option>
|
||||
</a-select>
|
||||
@ -61,16 +96,89 @@
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="所属服务组织" name="stationLables">
|
||||
<node-tree v-model:value="formData.stationLables" />
|
||||
<a-col :span="12">
|
||||
<a-form-item label="负责区域" name="sAreaCodes">
|
||||
<AreaCascader v-model:value="formData.sAreaCodes" @change="onAreaChange" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<!-- <a-col :span="8">
|
||||
<a-form-item label="组织所在区域" name="areaLabels">
|
||||
<node-tree v-model:value="formData.areaLabels" />
|
||||
<a-col :span="12">
|
||||
<a-form-item label="提成比例" name="commissionRate">
|
||||
<a-input-number v-model:value="formData.commissionRate" placeholder="请输入提成比例">
|
||||
<template #addonAfter>
|
||||
<span>%</span>
|
||||
</template>
|
||||
</a-input-number>
|
||||
</a-form-item>
|
||||
</a-col> -->
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="入职日期" name="joinAt">
|
||||
<a-date-picker v-model:value="formData.joinAt" placeholder="请选择入职日期" style="width: 100%;" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="资格证照注册号" name="qualificationNo">
|
||||
<a-input v-model:value="formData.qualificationNo" placeholder="请输入资格证照注册号" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="劳动合同期限" name="laborContract">
|
||||
<a-range-picker v-model:value="formData.laborContract" placeholder="请选择劳动合同期限" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="星级评价等级" name="starLv">
|
||||
<a-select v-model:value="formData.starLv" allowClear>
|
||||
<a-select-option v-for="item in dicsStore.dictOptions.START_LV" :key="item.dval"
|
||||
:value="item.dval">{{
|
||||
item.introduction }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="开户行名称" name="bankName">
|
||||
<a-input v-model:value="formData.bankName" placeholder="请输入开户行名称" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="银行卡号" name="bankNo">
|
||||
<a-input v-model:value="formData.bankNo" placeholder="请输入银行卡号" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="补贴类型" name="subsidyType">
|
||||
<a-select v-model:value="formData.subsidyType" allowClear>
|
||||
<a-select-option v-for="item in dicsStore.dictOptions.SUBSIDY_TYPE" :key="item.dval"
|
||||
:value="item.dval">{{
|
||||
item.introduction }}</a-select-option>
|
||||
</a-select>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="家庭地址" name="areaCodes">
|
||||
<AreaCascader v-model:value="formData.areaCodes" @change="onAreaChange2" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="家庭详细地址" name="address">
|
||||
<a-input v-model:value="formData.address" placeholder="请输入家庭详细地址"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="备注" name="remark">
|
||||
<a-textarea v-model:value="formData.remark" placeholder="请输入备注" :rows="4"></a-textarea>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="证件照片" name="imgs">
|
||||
<gx-upload v-model="formData.imgs" accept-types=".jpg,.png,.webp" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="12">
|
||||
<a-form-item label="附件" name="attachments">
|
||||
<gx-upload v-model="formData.attachments" accept-types=".jpg,.png,.webp,.xlsx,.docx,.doc" />
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-card>
|
||||
@ -87,33 +195,84 @@ import { useForm, useModal } from '@/hooks'
|
||||
import { useDicsStore } from '@/store'
|
||||
import AreaCascader from '@/components/AreaCascader/index.vue'
|
||||
import NodeTree from '@/components/NodeTree/index.vue'
|
||||
import dayjs from 'dayjs'
|
||||
import { getBirthDate, spliceUrl } from '@/utils/util'
|
||||
import { validatePhone, validateEmail, validateIdCard } from '@/utils/validate'
|
||||
const emit = defineEmits(['ok'])
|
||||
const activeKey = ref('1')
|
||||
const { modal, showModal, hideModal, showLoading, hideLoading } = useModal()
|
||||
const { formRecord, formData, formRef, formRules, resetForm } = useForm()
|
||||
const cancelText = ref('取消')
|
||||
const dicsStore = useDicsStore()
|
||||
|
||||
|
||||
const stationList=ref([])
|
||||
formRules.value={
|
||||
stationId: [{ required: true, message: '请选择服务组织',trigger: ['blur','change']}],
|
||||
name: [{ required: true, message: '请输入姓名',trigger: 'blur' }],
|
||||
idCard: [{ validator: validateIdCard, trigger: ['blur', 'input'] }, { required: true, message: '请输入联系方式', trigger: 'blur' }],
|
||||
phone: [{ validator: validatePhone, trigger: ['blur', 'input'] }, { required: true, message: '请输入联系方式', trigger: 'blur' }],
|
||||
serviceType: [{ required: true, message: '请选择护理人员类型',trigger: ['blur','change']}],
|
||||
insuranceStatus: [{ required: true, message: '请选择参保情况',trigger: ['blur','change']}],
|
||||
}
|
||||
/**
|
||||
* 新建
|
||||
*/
|
||||
function handleCreate() {
|
||||
formData.value.gender='1'
|
||||
showModal({
|
||||
type: 'create',
|
||||
title: '新增服务人员',
|
||||
})
|
||||
}
|
||||
getStationList()
|
||||
async function getStationList(){
|
||||
try {
|
||||
showLoading()
|
||||
const { success, data, total } = await apis.serviceMenu
|
||||
.getServiceSiteList({
|
||||
pageSize:100,
|
||||
current: 1,
|
||||
})
|
||||
.catch(() => {
|
||||
throw new Error()
|
||||
})
|
||||
hideLoading()
|
||||
if (config('http.code.success') === success) {
|
||||
//筛选type的值80对应about
|
||||
stationList.value = data.map(item=>({id:item.id,name:item.name}))
|
||||
}
|
||||
} catch (error) {
|
||||
hideLoading()
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 编辑
|
||||
*/
|
||||
function handleEdit(record = {}) {
|
||||
showModal({
|
||||
type: 'edit',
|
||||
title: '编辑项',
|
||||
})
|
||||
formRecord.value = record
|
||||
formData.value = cloneDeep(record)
|
||||
async function handleEdit(record = {}) {
|
||||
try {
|
||||
showModal({
|
||||
type: 'edit',
|
||||
title: '编辑项',
|
||||
})
|
||||
const { data, success } = await apis.serviceStaffList.getItem(record.id).catch()
|
||||
if (!success) {
|
||||
hideModal()
|
||||
return
|
||||
}
|
||||
formRecord.value = data
|
||||
if (formData.value.joinAt) {
|
||||
formData.value.joinAt = dayjs(formData.value.joinAt)
|
||||
}
|
||||
if (formData.value.laborContractStartAt && formData.value.laborContractEndAt) {
|
||||
formData.value.laborContract = [dayjs(formData.value.laborContractStartAt), dayjs(formData.value.laborContractEndAt)]
|
||||
}
|
||||
formData.value.imgs = (data.imgs && data.imgs.length > 0) ? data.imgs.map(item => config('http.apiBasic') + item) : []
|
||||
formData.value.attachments = (data.attachments && data.attachments.length > 0) ? data.attachments.map(item => config('http.apiBasic') + item) : []
|
||||
formData.value.commissionRate=formData.value.commissionRate??formData.value.commissionRate*100
|
||||
formData.value.birthDate2=dayjs(data.birthDate).format('YYYY-DD-MM')
|
||||
} catch (error) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -126,28 +285,39 @@ function handleOk() {
|
||||
.then(async (values) => {
|
||||
try {
|
||||
showLoading()
|
||||
const params = {
|
||||
let params = {
|
||||
...formData.value,
|
||||
birthDate:new Date(formData.value.birthDate)
|
||||
}
|
||||
|
||||
if (formData.value.laborContract && formData.value.laborContract.length > 0) {
|
||||
params.laborContractStartAt = formData.value.laborContract[0]
|
||||
params.laborContractEndAt = formData.value.laborContract[1]
|
||||
}
|
||||
params.imgs = (formData.value.imgs&&formData.value.imgs.length) > 0 ? formData.value.imgs.map(item => spliceUrl(item)) : ['']
|
||||
params.attachments = (formData.value.attachments&&formData.value.attachments.length) > 0 ? formData.value.attachments.map(item => spliceUrl(item)) : ['']
|
||||
params.commissionRate=formData.value.commissionRate??formData.value.commissionRate/100
|
||||
console.log(params)
|
||||
let result = null
|
||||
switch (modal.value.type) {
|
||||
case 'create':
|
||||
result = await apis.serverObj.createItem(params).catch(() => {
|
||||
result = await apis.serviceStaffList.createItem(params).catch(() => {
|
||||
throw new Error()
|
||||
})
|
||||
break
|
||||
case 'edit':
|
||||
result = await apis.serverObj.updateItem(params).catch(() => {
|
||||
result = await apis.serviceStaffList.updateItem(params).catch(() => {
|
||||
throw new Error()
|
||||
})
|
||||
break
|
||||
}
|
||||
hideLoading()
|
||||
if (config('http.code.success') === result?.code) {
|
||||
if (config('http.code.success') === true) {
|
||||
hideModal()
|
||||
emit('ok')
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error.message)
|
||||
hideLoading()
|
||||
}
|
||||
})
|
||||
@ -155,7 +325,24 @@ function handleOk() {
|
||||
hideLoading()
|
||||
})
|
||||
}
|
||||
|
||||
// 提取出生日期方法
|
||||
const extractBirthDateFromIdCard = () => {
|
||||
console.log(111)
|
||||
const { idCard } = formData.value;
|
||||
if (!idCard) {
|
||||
formData.value.birthDate = '';
|
||||
return;
|
||||
}
|
||||
console.log(getBirthDate(idCard))
|
||||
formData.value.birthDate2=getBirthDate(idCard)
|
||||
formData.value.birthDate =new Date(getBirthDate(idCard));
|
||||
}
|
||||
function onAreaChange(value, labels) {
|
||||
formData.value.sAreaLabels = [...labels]
|
||||
}
|
||||
function onAreaChange2(value, labels) {
|
||||
formData.value.areaLabels = [...labels]
|
||||
}
|
||||
/**
|
||||
* 取消
|
||||
*/
|
||||
|
||||
@ -78,6 +78,14 @@
|
||||
<template v-if="column.key === 'serialNumber'">
|
||||
<span>{{ index + 1 }}</span>
|
||||
</template>
|
||||
<template v-if="column.key === 'gender'">
|
||||
<span v-if="record.gender=='1'">男</span>
|
||||
<span v-else>女</span>
|
||||
</template>
|
||||
<template v-if="column.key === 'serviceType'">
|
||||
<span>{{ dicsStore.getDictLabel('STAFF_TYPE', record.serviceType) }}</span>
|
||||
</template>
|
||||
|
||||
<template v-if="'action' === column.key">
|
||||
<x-action-button @click="$refs.editDialogRef.handleEdit(record)">
|
||||
<span>编辑</span>
|
||||
@ -170,14 +178,6 @@ const columns = [
|
||||
align: 'center',
|
||||
width: 120,
|
||||
},
|
||||
// --- 联系方式 ---
|
||||
{
|
||||
title: '护理人员类型',
|
||||
dataIndex: 'serviceType',
|
||||
key: 'serviceType',
|
||||
align: 'center',
|
||||
width: 130,
|
||||
},
|
||||
{
|
||||
title: '所属服务组织',
|
||||
dataIndex: 'stationName',
|
||||
|
||||
47
yarn.lock
47
yarn.lock
@ -175,7 +175,7 @@
|
||||
resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.22.5.tgz"
|
||||
integrity sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==
|
||||
|
||||
"@babel/runtime@^7.10.5":
|
||||
"@babel/runtime@^7.10.5", "@babel/runtime@^7.5.5":
|
||||
version "7.18.6"
|
||||
resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.6.tgz"
|
||||
integrity sha512-t9wi7/AW6XtKahAe20Yw0/mMljKq0B1r2fPdvaAdV/KPDZewFXdaaa6K7lxmZBZ8FBNpCiAT6iHPmd6QO9bKfQ==
|
||||
@ -302,6 +302,51 @@
|
||||
resolved "https://registry.npmmirror.com/@intlify/shared/-/shared-9.14.4.tgz"
|
||||
integrity sha512-P9zv6i1WvMc9qDBWvIgKkymjY2ptIiQ065PjDv7z7fDqH3J/HBRBN5IoiR46r/ujRcU7hCuSIZWvCAFCyuOYZA==
|
||||
|
||||
"@jiaminghi/bezier-curve@*":
|
||||
version "0.0.9"
|
||||
resolved "https://registry.npmmirror.com/@jiaminghi/bezier-curve/-/bezier-curve-0.0.9.tgz"
|
||||
integrity sha512-u9xJPOEl6Dri2E9FfmJoGxYQY7vYJkURNX04Vj64tdi535tPrpkuf9Sm0lNr3QTKdHQh0DdNRsaa62FLQNQEEw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.5.5"
|
||||
|
||||
"@jiaminghi/c-render@^0.4.3":
|
||||
version "0.4.3"
|
||||
resolved "https://registry.npmmirror.com/@jiaminghi/c-render/-/c-render-0.4.3.tgz"
|
||||
integrity sha512-FJfzj5hGj7MLqqqI2D7vEzHKbQ1Ynnn7PJKgzsjXaZpJzTqs2Yw5OSeZnm6l7Qj7jyPAP53lFvEQNH4o4j6s+Q==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.5.5"
|
||||
"@jiaminghi/bezier-curve" "*"
|
||||
"@jiaminghi/color" "*"
|
||||
"@jiaminghi/transition" "*"
|
||||
|
||||
"@jiaminghi/charts@*":
|
||||
version "0.2.18"
|
||||
resolved "https://registry.npmmirror.com/@jiaminghi/charts/-/charts-0.2.18.tgz"
|
||||
integrity sha512-K+HXaOOeWG9OOY1VG6M4mBreeeIAPhb9X+khG651AbnwEwL6G2UtcAQ8GWCq6GzhczcLwwhIhuaHqRygwHC0sA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.5.5"
|
||||
"@jiaminghi/c-render" "^0.4.3"
|
||||
|
||||
"@jiaminghi/color@*":
|
||||
version "1.1.3"
|
||||
resolved "https://registry.npmmirror.com/@jiaminghi/color/-/color-1.1.3.tgz"
|
||||
integrity sha512-ZY3hdorgODk4OSTbxyXBPxAxHPIVf9rPlKJyK1C1db46a50J0reFKpAvfZG8zMG3lvM60IR7Qawgcu4ZDO3+Hg==
|
||||
|
||||
"@jiaminghi/data-view@^2.10.0":
|
||||
version "2.10.0"
|
||||
resolved "https://registry.npmmirror.com/@jiaminghi/data-view/-/data-view-2.10.0.tgz"
|
||||
integrity sha512-Cud2MTiMcqc5k2KWabR/svuVQmXHANqURo+yj40370/LdI/gyUJ6LG203hWXEnT1nMCeiv/SLVmxv3PXLScCeA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.5.5"
|
||||
"@jiaminghi/charts" "*"
|
||||
|
||||
"@jiaminghi/transition@*":
|
||||
version "1.1.11"
|
||||
resolved "https://registry.npmmirror.com/@jiaminghi/transition/-/transition-1.1.11.tgz"
|
||||
integrity sha512-owBggipoHMikDHHDW5Gc7RZYlVuvxHADiU4bxfjBVkHDAmmck+fCkm46n2JzC3j33hWvP9nSCAeh37t6stgWeg==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.5.5"
|
||||
|
||||
"@jridgewell/sourcemap-codec@^1.4.13":
|
||||
version "1.4.15"
|
||||
resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user