会议功能调整

This commit is contained in:
z9130 2024-09-28 12:17:08 +08:00
parent 0ffde22662
commit 736de72e9d
13 changed files with 300 additions and 49 deletions

View File

@ -0,0 +1,63 @@
const createEntry = (description = '', data: any = []) => ({
description,
data,
});
const staticDicts = {
cancel_reson: createEntry('变更原因', [
{ label: '未填写原因', value: '0' },
{ label: '用户取消', value: '1' },
{ label: '系统取消', value: '2' },
{ label: '其他原因', value: '3' },
]),
};
export default {
// 配置路径,如果存在,则使用配置路径下的文件
configPath: '',
// 接口配置,仅用于生成 api 接口文件
apis: {
enable: true,
generator: [
{
input: '',
templatePath: 'src/api/template',
output: 'src/api/index.ts',
needTs: true,
outputTs: 'src/api/globals.d.ts',
handleApi: (apiDescriptor) => {
// 返回falsy值表示过滤此api
if (!apiDescriptor.path.startWith('/user')) {
return;
}
apiDescriptor.parameter = apiDescriptor.parameter.filter(
(param) => param.in === 'header' && param.name === 'token',
);
delete apiDescriptor.requestBody.id;
apiDescriptor.url = apiDescriptor.url.replace('/user', '');
return apiDescriptor;
},
},
],
},
// 字典配置,仅用于生成字典枚举文件
dicts: {
enable: true,
generator: [
{
input: '',
templatePath: 'src/api/template',
output: 'src/utils/dict/shared.ts',
handleDict: async (dictDescriptor) => {
// await dictDescriptor.request();
// 请求数据类型表为了生成对应注释
// 返回falsy值表示过滤此api
staticDicts[dictDescriptor.name] = dictDescriptor;
return dictDescriptor;
},
},
],
},
};

View File

@ -33,7 +33,7 @@ const tokenTheme = computed(() => {
const dictStore = useDictStore(); const dictStore = useDictStore();
if (dictStore.initDict) { if (dictStore.initDict) {
dictStore.setDictMap(); // dictStore.setDictMap();
} }
</script> </script>

View File

@ -3,12 +3,6 @@ import { unmountGlobalLoading } from '@vben/utils';
import { overridesPreferences } from './preferences'; import { overridesPreferences } from './preferences';
// const dict = new Dictionary(http.get, {});
// dict.getAll('dict').then((res) => {
// console.log('dict', res);
// });
/** /**
* *
*/ */

View File

@ -1,5 +1,7 @@
/** 数据字典工具类 */ /** 数据字典工具类 */
import Apis from '#/api';
import { useDictStore } from '#/store/dict'; import { useDictStore } from '#/store/dict';
import dataModule from '#/utils/dict/static.data';
export * from './shared'; export * from './shared';
@ -12,9 +14,9 @@ const dictStore = useDictStore();
* @returns {any | Array} * @returns {any | Array}
*/ */
export interface DictDataType { export interface DictDataType {
dictTyp?: string; dictType?: string;
label: string; label: string;
value: null | number | string; value: boolean | null | number | string;
key?: any; key?: any;
colorType?: string; colorType?: string;
cssClass?: string; cssClass?: string;
@ -39,6 +41,58 @@ export function getDictOpts(dictType: string) {
return getDictDatas(dictType); return getDictDatas(dictType);
} }
export async function getDictDatasAsync(dictTypes: string[]) {
const dictDataMap: Record<string, DictDataType[]> = {};
const foundTypes = new Set<string>();
// Process static dictionary data
for (const dictType of Object.keys(dataModule)) {
if (dictTypes.includes(dictType)) {
const dictEntries = dataModule[dictType];
dictEntries.data.forEach((dictData) => {
dictData.type = dictType;
if (!dictDataMap[dictType]) {
dictDataMap[dictType] = [];
}
dictDataMap[dictType].push({
...dictData,
value: dictData.value,
label: dictData.name,
colorType: dictData.colorType,
cssClass: dictData.cssClass,
} as DictDataType);
});
foundTypes.add(dictType);
// If all types are found, return early
if (foundTypes.size === dictTypes.length) {
return dictDataMap;
}
}
}
// Fetch remote dictionary data in parallel
const promises = dictTypes.map(async (type) => {
if (!foundTypes.has(type)) {
try {
const data = await Apis.dictData.get_page({ params: { type } });
dictDataMap[type] = (data.rows || []).map((dictData: any) => ({
value: dictData.value,
label: dictData.name,
colorType: dictData.colorType,
cssClass: dictData.cssClass,
}));
} catch (error) {
console.error(`Failed to fetch data for type ${type}:`, error);
}
}
});
await Promise.all(promises);
return dictDataMap;
}
export function getDictOptions( export function getDictOptions(
dictType: string, dictType: string,
valueType?: 'boolean' | 'number' | 'string', valueType?: 'boolean' | 'number' | 'string',
@ -52,12 +106,7 @@ export function getDictOptions(
dictOption.push({ dictOption.push({
...dict, ...dict,
key: dict.value, key: dict.value,
value: value: convertValue(dict.value, valueType),
valueType === 'string'
? `${dict.value}`
: valueType === 'boolean'
? `${dict.value}` === 'true'
: Number.parseInt(`${dict.value}`),
}); });
}); });
} }
@ -65,6 +114,41 @@ export function getDictOptions(
return dictOption; return dictOption;
} }
function convertValue(value, type) {
switch (type) {
case 'boolean': {
return value === 'true';
}
case 'number': {
return Number.parseInt(value, 10);
}
case 'string': {
return String(value);
}
default: {
return value;
}
}
}
export async function getDictOptionsAsync(
dictType: string,
valueType: 'boolean' | 'number' | 'string' = 'string',
): Promise<DictDataType[]> {
try {
const response = await getDictDatasAsync([dictType]);
const dictOptions: DictDataType[] = response[dictType] || [];
return dictOptions.map((dict: DictDataType) => ({
...dict,
key: dict.value,
value: convertValue(dict.value, valueType),
}));
} catch (error) {
console.error('Error fetching dictionary data:', error);
return [];
}
}
/** 获取指定 value 的字典数据 */ /** 获取指定 value 的字典数据 */
export function getDictObj(dictType: string, value: any): DictDataType | null { export function getDictObj(dictType: string, value: any): DictDataType | null {
const dictOptions: DictDataType[] = getDictDatas(dictType); const dictOptions: DictDataType[] = getDictDatas(dictType);

View File

@ -8,7 +8,12 @@ import dayjs, { type Dayjs } from 'dayjs';
import { VxeGrid, type VxeGridPropTypes } from 'vxe-table'; import { VxeGrid, type VxeGridPropTypes } from 'vxe-table';
import { unitComponentProps } from '#/common/unit'; import { unitComponentProps } from '#/common/unit';
import { DICT_TYPE, getDictObj, getDictOptions } from '#/utils/dict'; import {
DICT_TYPE,
getDictObj,
getDictOptions,
getDictOptionsAsync,
} from '#/utils/dict';
import chooseUserModal from '#/views/system/user/choose-user-modal.vue'; import chooseUserModal from '#/views/system/user/choose-user-modal.vue';
const [ChooseUserModal, chooseUserModalApi] = useVbenModal({ const [ChooseUserModal, chooseUserModalApi] = useVbenModal({
@ -122,7 +127,11 @@ export function getFormSchema(params?: any): any {
vModel: 'value', vModel: 'value',
allowClear: false, allowClear: false,
dict: dict({ dict: dict({
data: getDictOptions(DICT_TYPE.contract_authorization_type2), async getData(_context) {
return await getDictOptionsAsync(
DICT_TYPE.contract_authorization_type2,
);
},
}), }),
}, },
valueChange: { valueChange: {

View File

@ -30,7 +30,7 @@ export default defineConfig(async () => {
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/api\/app/, '/'), rewrite: (path) => path.replace(/^\/api\/app/, '/'),
// target: `http://10.71.220.24:8083/rl`, // target: `http://10.71.220.24:8083/rl`,
target: `http://192.168.148.88:8083/rl`, target: `http://192.168.147.164:8083/rl`,
ws: true, ws: true,
}, },
'/api/czg/app': { '/api/czg/app': {
@ -43,15 +43,15 @@ export default defineConfig(async () => {
'/api/czg/uc': { '/api/czg/uc': {
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/api\/czg\/uc/, '/'), rewrite: (path) => path.replace(/^\/api\/czg\/uc/, '/'),
target: `http://192.168.148.88:8082`, target: `http://192.168.147.164:8082`,
// target: `http://192.168.148.88:8082`, // target: `http://192.168.147.164:8082`,
ws: true, ws: true,
}, },
'/api/uc': { '/api/uc': {
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/api\/uc/, '/'), rewrite: (path) => path.replace(/^\/api\/uc/, '/'),
// target: `http://10.71.220.24:8082`, // target: `http://10.71.220.24:8082`,
target: `http://192.168.148.88:8082`, target: `http://192.168.147.164:8082`,
ws: true, ws: true,
}, },
'/api/xmh/app': { '/api/xmh/app': {
@ -65,7 +65,7 @@ export default defineConfig(async () => {
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/api\/xmh\/uc/, '/'), rewrite: (path) => path.replace(/^\/api\/xmh\/uc/, '/'),
// mock代理目标地址 // mock代理目标地址
target: `http://192.168.148.88:8082`, target: `http://192.168.147.164:8082`,
ws: true, ws: true,
}, },
'/api/zp/app': { '/api/zp/app': {
@ -79,21 +79,21 @@ export default defineConfig(async () => {
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/api\/zp\/uc/, '/'), rewrite: (path) => path.replace(/^\/api\/zp\/uc/, '/'),
// mock代理目标地址 // mock代理目标地址
target: `http://192.168.148.88:8082`, target: `http://192.168.147.164:8082`,
ws: true, ws: true,
}, },
'/api/zzz/app': { '/api/zzz/app': {
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/api\/zzz\/app/, '/'), rewrite: (path) => path.replace(/^\/api\/zzz\/app/, '/'),
// target: `http://192.168.0.193:8083/rl`, // target: `http://192.168.0.193:8083/rl`,
target: `http://192.168.148.88:8089/rl`, target: `http://192.168.147.164:8089/rl`,
ws: true, ws: true,
}, },
'/api/zzz/uc': { '/api/zzz/uc': {
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/api\/zzz\/uc/, '/'), rewrite: (path) => path.replace(/^\/api\/zzz\/uc/, '/'),
target: `http://192.168.148.88:8082`, target: `http://192.168.147.164:8082`,
// target: `http://192.168.148.88:8082`, // target: `http://192.168.147.164:8082`,
ws: true, ws: true,
}, },
}, },

View File

@ -1,5 +1,7 @@
/** 数据字典工具类 */ /** 数据字典工具类 */
import Apis from '#/api';
import { useDictStore } from '#/store/dict'; import { useDictStore } from '#/store/dict';
import dataModule from '#/utils/dict/static.data';
export * from './shared'; export * from './shared';
@ -12,9 +14,9 @@ const dictStore = useDictStore();
* @returns {any | Array} * @returns {any | Array}
*/ */
export interface DictDataType { export interface DictDataType {
dictTyp?: string; dictType?: string;
label: string; label: string;
value: null | number | string; value: boolean | null | number | string;
key?: any; key?: any;
colorType?: string; colorType?: string;
cssClass?: string; cssClass?: string;
@ -39,6 +41,58 @@ export function getDictOpts(dictType: string) {
return getDictDatas(dictType); return getDictDatas(dictType);
} }
export async function getDictDatasAsync(dictTypes: string[]) {
const dictDataMap: Record<string, DictDataType[]> = {};
const foundTypes = new Set<string>();
// Process static dictionary data
for (const dictType of Object.keys(dataModule)) {
if (dictTypes.includes(dictType)) {
const dictEntries = dataModule[dictType];
dictEntries.data.forEach((dictData) => {
dictData.type = dictType;
if (!dictDataMap[dictType]) {
dictDataMap[dictType] = [];
}
dictDataMap[dictType].push({
...dictData,
value: dictData.value,
label: dictData.name,
colorType: dictData.colorType,
cssClass: dictData.cssClass,
} as DictDataType);
});
foundTypes.add(dictType);
// If all types are found, return early
if (foundTypes.size === dictTypes.length) {
return dictDataMap;
}
}
}
// Fetch remote dictionary data in parallel
const promises = dictTypes.map(async (type) => {
if (!foundTypes.has(type)) {
try {
const data = await Apis.dictData.get_page({ params: { type } });
dictDataMap[type] = (data.rows || []).map((dictData: any) => ({
value: dictData.value,
label: dictData.name,
colorType: dictData.colorType,
cssClass: dictData.cssClass,
}));
} catch (error) {
console.error(`Failed to fetch data for type ${type}:`, error);
}
}
});
await Promise.all(promises);
return dictDataMap;
}
export function getDictOptions( export function getDictOptions(
dictType: string, dictType: string,
valueType?: 'boolean' | 'number' | 'string', valueType?: 'boolean' | 'number' | 'string',
@ -52,12 +106,7 @@ export function getDictOptions(
dictOption.push({ dictOption.push({
...dict, ...dict,
key: dict.value, key: dict.value,
value: value: convertValue(dict.value, valueType),
valueType === 'string'
? `${dict.value}`
: valueType === 'boolean'
? `${dict.value}` === 'true'
: Number.parseInt(`${dict.value}`),
}); });
}); });
} }
@ -65,6 +114,41 @@ export function getDictOptions(
return dictOption; return dictOption;
} }
function convertValue(value, type) {
switch (type) {
case 'boolean': {
return value === 'true';
}
case 'number': {
return Number.parseInt(value, 10);
}
case 'string': {
return String(value);
}
default: {
return value;
}
}
}
export async function getDictOptionsAsync(
dictType: string,
valueType: 'boolean' | 'number' | 'string' = 'string',
): Promise<DictDataType[]> {
try {
const response = await getDictDatasAsync([dictType]);
const dictOptions: DictDataType[] = response[dictType] || [];
return dictOptions.map((dict: DictDataType) => ({
...dict,
key: dict.value,
value: convertValue(dict.value, valueType),
}));
} catch (error) {
console.error('Error fetching dictionary data:', error);
return [];
}
}
/** 获取指定 value 的字典数据 */ /** 获取指定 value 的字典数据 */
export function getDictObj(dictType: string, value: any): DictDataType | null { export function getDictObj(dictType: string, value: any): DictDataType | null {
const dictOptions: DictDataType[] = getDictDatas(dictType); const dictOptions: DictDataType[] = getDictDatas(dictType);

View File

@ -4,7 +4,7 @@ import { dict } from '@fast-crud/fast-crud';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { useRender } from '#/hooks/useRender'; import { useRender } from '#/hooks/useRender';
import { DICT_TYPE, getDictOptions } from '#/utils/dict'; import { DICT_TYPE, getDictOptionsAsync } from '#/utils/dict';
export const PrimaryKey = 'guid'; export const PrimaryKey = 'guid';
@ -31,7 +31,7 @@ export function getColumns(params: any = {}): VxeGridPropTypes.Columns {
}, },
}, },
{ {
field: 'meetingDate', field: 'meetingInfo',
title: '会议信息', title: '会议信息',
width: 200, width: 200,
slots: { default: 'meetingInfoSlot' }, slots: { default: 'meetingInfoSlot' },
@ -171,7 +171,9 @@ export function getFormSchema(_params: any = {}) {
class: 'min-w-[180px]', class: 'min-w-[180px]',
allowClear: true, allowClear: true,
dict: dict({ dict: dict({
data: getDictOptions(DICT_TYPE.meeting_room), async getData() {
return await getDictOptionsAsync(DICT_TYPE.meeting_room);
},
}), }),
}, },
autoSearchTrigger: 'enter', autoSearchTrigger: 'enter',
@ -186,7 +188,9 @@ export function getFormSchema(_params: any = {}) {
class: 'min-w-[180px]', class: 'min-w-[180px]',
allowClear: true, allowClear: true,
dict: dict({ dict: dict({
data: getDictOptions(DICT_TYPE.meeting_type), async getData() {
return await getDictOptionsAsync(DICT_TYPE.meeting_type);
},
}), }),
}, },
autoSearchTrigger: 'enter', autoSearchTrigger: 'enter',

View File

@ -12,7 +12,7 @@ export function getColumns(_params?: any): VxeGridPropTypes.Columns {
{ {
field: 'meetingDate', field: 'meetingDate',
title: '会议时间', title: '会议时间',
width: 200, width: 230,
slots: { slots: {
default: ({ row }) => { default: ({ row }) => {
return ( return (
@ -49,7 +49,7 @@ export function getColumns(_params?: any): VxeGridPropTypes.Columns {
{ {
field: 'otherEquipment', field: 'otherEquipment',
title: '备注', title: '备注',
minWidth: 200, minWidth: 150,
}, },
]; ];

View File

@ -143,7 +143,7 @@ const searchForm = ref({
<style scoped> <style scoped>
:deep(.vxe-table--render-default.size--medium) { :deep(.vxe-table--render-default.size--medium) {
font-size: 20px; font-size: 18px;
} }
:deep(.ant-form-item .ant-form-item-label > label) { :deep(.ant-form-item .ant-form-item-label > label) {
font-size: 16px !important; font-size: 16px !important;

View File

@ -32,6 +32,7 @@ const currentSpeaker = computed(() => addressorData.value[currentIndex.value]);
const textSize = ref('text-2xl'); const textSize = ref('text-2xl');
const textColor = ref('text-gray-700'); const textColor = ref('text-gray-700');
const bgColor = ref('bg-gray-50'); const bgColor = ref('bg-gray-50');
const isBold = ref(false);
const currData = ref({ const currData = ref({
guid: '', guid: '',
@ -275,7 +276,7 @@ function downloadFile(fileUrl) {
会议状态: 已开始 会议状态: 已开始
</div> </div>
<!-- Action Bar --> <!-- Action Bar -->
<div class="flex justify-center space-x-4"> <div class="flex items-center justify-center space-x-4">
<div v-if="meetingStarted"> <div v-if="meetingStarted">
<label class="font-bold text-gray-700">文字大小:</label> <label class="font-bold text-gray-700">文字大小:</label>
<select v-model="textSize" class="ml-2 rounded border-gray-300 p-1"> <select v-model="textSize" class="ml-2 rounded border-gray-300 p-1">
@ -283,6 +284,7 @@ function downloadFile(fileUrl) {
<option value="text-lg"></option> <option value="text-lg"></option>
<option value="text-2xl"></option> <option value="text-2xl"></option>
<option value="text-3xl">超大</option> <option value="text-3xl">超大</option>
<option value="text-4xl">特大</option>
</select> </select>
</div> </div>
<div v-if="meetingStarted"> <div v-if="meetingStarted">
@ -293,6 +295,7 @@ function downloadFile(fileUrl) {
<option value="text-red-500">红色</option> <option value="text-red-500">红色</option>
<option value="text-blue-500">蓝色</option> <option value="text-blue-500">蓝色</option>
<option value="text-green-500">绿色</option> <option value="text-green-500">绿色</option>
<option value="text-white">白色</option>
</select> </select>
</div> </div>
<div v-if="meetingStarted"> <div v-if="meetingStarted">
@ -303,8 +306,13 @@ function downloadFile(fileUrl) {
<option value="bg-green-50">浅绿</option> <option value="bg-green-50">浅绿</option>
<option value="bg-yellow-50">浅黄</option> <option value="bg-yellow-50">浅黄</option>
<option value="bg-red-50">浅红</option> <option value="bg-red-50">浅红</option>
<option value="bg-[#03055a]">深蓝</option>
</select> </select>
</div> </div>
<div v-if="meetingStarted">
<label class="font-bold text-gray-700">加粗:</label>
<input v-model="isBold" class="ml-2" type="checkbox" />
</div>
</div> </div>
</div> </div>
@ -364,7 +372,7 @@ function downloadFile(fileUrl) {
class="content-area mb-4 flex h-[50vh] items-center overflow-y-auto rounded-lg p-4" class="content-area mb-4 flex h-[50vh] items-center overflow-y-auto rounded-lg p-4"
> >
<p <p
:class="[textColor, textSize]" :class="[textColor, textSize, { 'font-bold': isBold }]"
class="text-left" class="text-left"
style="white-space: pre-line" style="white-space: pre-line"
> >
@ -418,6 +426,11 @@ function downloadFile(fileUrl) {
addressorData[currentIndex + 1].addressor addressorData[currentIndex + 1].addressor
}}</span> }}</span>
</button> </button>
<span
v-if="currentIndex === addressorData.length - 1"
class="text-xl font-bold"
>科室及基层车间发言全部结束领导讲话正在进行中请两办秘书做好记录</span
>
<button <button
v-if="currentIndex === addressorData.length - 1" v-if="currentIndex === addressorData.length - 1"
class="rounded-lg bg-red-500 px-4 py-2 font-bold text-white transition hover:bg-red-600" class="rounded-lg bg-red-500 px-4 py-2 font-bold text-white transition hover:bg-red-600"

View File

@ -30,14 +30,14 @@ export default defineConfig(async () => {
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/api\/app/, '/'), rewrite: (path) => path.replace(/^\/api\/app/, '/'),
// target: `http://10.71.220.24:8083/rl`, // target: `http://10.71.220.24:8083/rl`,
target: `http://192.168.148.88:8083/rl`, target: `http://192.168.147.164:8083/rl`,
ws: true, ws: true,
}, },
'/api/uc': { '/api/uc': {
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/api\/uc/, '/'), rewrite: (path) => path.replace(/^\/api\/uc/, '/'),
// target: `http://10.71.220.24:8082`, // target: `http://10.71.220.24:8082`,
target: `http://192.168.148.88:8082`, target: `http://192.168.147.164:8082`,
ws: true, ws: true,
}, },
'/api/czg/app': { '/api/czg/app': {
@ -51,7 +51,7 @@ export default defineConfig(async () => {
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/api\/czg\/uc/, '/'), rewrite: (path) => path.replace(/^\/api\/czg\/uc/, '/'),
// mock代理目标地址 // mock代理目标地址
target: `http://192.168.148.88:8082`, target: `http://192.168.147.164:8082`,
ws: true, ws: true,
}, },
'/api/zp/app': { '/api/zp/app': {
@ -65,7 +65,7 @@ export default defineConfig(async () => {
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/api\/zp\/uc/, '/'), rewrite: (path) => path.replace(/^\/api\/zp\/uc/, '/'),
// mock代理目标地址 // mock代理目标地址
target: `http://192.168.148.88:8082`, target: `http://192.168.147.164:8082`,
ws: true, ws: true,
}, },
'/api/xmh/app': { '/api/xmh/app': {
@ -80,7 +80,7 @@ export default defineConfig(async () => {
changeOrigin: true, changeOrigin: true,
rewrite: (path) => path.replace(/^\/api\/xmh\/uc/, '/'), rewrite: (path) => path.replace(/^\/api\/xmh\/uc/, '/'),
// mock代理目标地址 // mock代理目标地址
target: `http://192.168.148.88:8082`, target: `http://192.168.147.164:8082`,
ws: true, ws: true,
}, },
}, },

View File

@ -1,6 +1,6 @@
// export * from './logger/index'; // export * from './logger/index';
export * from './dict/index'; export * from './dict/index';
export * from './utils/index'; export * from './utils/logger';
// export const logger = { // export const logger = {
// log(level: string, message: any, error?: any) { // log(level: string, message: any, error?: any) {
// const timestamp = new Date().toISOString(); // const timestamp = new Date().toISOString();