JeeSite — платформа быстрого разработки, с минимальным кодированием, легковесная, не только серверный фреймворк, но и полное решение для быстрой разработки корпоративных приложений. Серверная часть основана на классическом сочетании Spring Boot, Shiro, MyBatis, а клиентская часть использует современные технологии: Vue3, Vite, Ant Design Vue, TypeScript, Vben Admin, или традиционные технологии: Beetl, Bootstrap, AdminLTE.* Предоставляет функции управления источниками данных, моделирования таблиц данных, генерации кода и т.д. Может автоматически создавать проекты кода для бизнес-модулей и микросервисов, генерировать фронтенд-код и бэкенд-код. Включает в себя основные модули, такие как: организация, пользователи, роли, должности, администраторы, аудит прав доступа, права доступа к меню и кнопкам, права доступа к данным, управление модулями, параметры системы, управление словарями, мониторинг системы, мониторинг данных и т.д. Расширенные функции включают: движок рабочих процессов, управление контентом, отправку уведомлений, единственный вход, вход через третьи стороны, планирование задач в реальном времени, объектное хранение, визуализацию данных, конструктор отчетов, просмотр файлов онлайн, интернационализацию, полнотекстовый поиск, единый сервис аутентификации и т.д.* Данная платформа использует декомпозиционную архитектуру, является легковесной, имеет микроядро, быструю установку, плагинную архитектуру, удобное добавление и удаление модулей, поддерживает расширение SaaS-архитектуры, кластерное развертывание, разделение чтения и записи, разделение баз данных и таблиц, архитектуру микросервисов Spring Cloud. Внутри встроены множество решений по безопасности, таких как настройки безопасности аккаунтов, политики паролей, ограничения доступа к системе и т. д., поддерживаются требования по защите информации. * Этот платформенный подход направлен на предоставление мощной поддержки для начинающих разработчиков, что позволяет им эффективно и быстро создавать сложные бизнес-функции. В то же время он освобождает ценных специалистов от рутинных задач, позволяя им сосредоточиться на более стратегических и инновационных задачах. Мы стремимся обеспечить разработчикам возможность полностью сконцентрироваться на бизнес-логике, передавая сложные технические детали на обработку платформе. Это не только снижает сложность технической реализации, но и гарантирует стабильность и безопасность архитектуры системы, что в конечном итоге помогает сократить затраты на персонал, сократить сроки проектов и повысить общую безопасность и качество программного обеспечения.* С момента выпуска в 2013 году продукт был использован в различных областях, включая предприятия, правительство, медицину, финансы и интернет. Он обладает тщательно продуманной архитектурой, легко расширяется и использует модели дизайна, ориентированные на массового пользователя. Разработчики вкладывают много времени и усилий в каждую деталь, чтобы соответствовать ожиданиям разработчиков, и за это они получили множество наград от Open China за "самый популярный китайский opensource-софт". Кроме того, этот продукт используется как учебное пособие для студентов и преподавателей, чтобы быстро применять полученные знания.* В 2019 году произошел переход на новую версию, в которой мы включили много лет опыта и примеры использования, полностью переработав архитектуру. Мы также внедрили новые идеи. В результате, как в режиме разработчика, так и в пользовательском интерфейсе, были достигнуты значительные улучшения. При этом мы сохранили низкую стоимость обучения и повысили эффективность разработки, обеспечивая высокий уровень безопасности, включая аутентификацию, политику паролей, аудит безопасности, сбор логов и другие опции безопасности.
В 2021 году был выпущен версионный разделённый на фронтенд и бэкенд Vue3, что позволило JeeSite поддерживать две технологии фронтенда — разделённую и полную стековую версию — с помощью одного и того же веб-сервера.
JeeSite поддерживает национальные стандарты программного обеспечения и аппаратного обеспечения, такие как национальные микропроцессоры, операционные системы, базы данных, промежуточные слои и алгоритмы шифрования.
Построен на передовых технологиях, таких как Vue3, Vite, Ant-Design-Vue, TypeScript и Vue Vben Admin, этот софт использует самую современную архитектуру, чтобы помочь новичкам быстро освоить технологию и влиться в команду разработчиков. Встроен ряд ключевых модулей, таких как организационная структура, роли пользователей, авторизация меню, права доступа к данным, параметры системы и т. д., что, в сочетании с мощными компонентами и данными, приводящими к динамическому дизайну интерфейса, обеспечивает готовые решения для малых, средних и крупных проектов, а также множество примеров для эффективной разработки.Интерфейс пользователя разработан специально для управления информационными системами. В дизайне интерфейса используется подход к совершенству, каждый элемент интерфейса подчеркивает его элегантность, обеспечивая пользователям удобный и интуитивно понятный опыт. Он предлагает разнообразные макеты меню, умное управление вкладками, эффективное управление деревьями, мощные компоненты таблиц и гибкие компоненты форм, обладая мощными возможностями расширения. Также поддерживает темную тему, обеспечивая пользователям эффективный, гибкий и красивый опыт, удовлетворяющий потребности различных систем управления.Кроме того, мы поддерживаем быстрое создание приложений с использованием Turborepo + Monorepo, модульное программирование, переиспользование кода и поддержку раздельной разработки модулей. Подробнее: https://gitee.com/thinkgem/jeesite-vue/tree/monorepo/
Определены множество компонентов, с удобными атрибутами компонентов и небольшими функциями, что соответствует идеологии дизайна JeeSite. Списки и формы используют данные для динамического дизайна интерфейса, что значительно упрощает разработку бизнес-функций. Подробное описание: Анализ исходного кода Почему следует использовать данные для драйверства представлений? Одной из самых больших проблем в фронтенде является обратная совместимость. С появлением соответствующих стандартов, обновление фреймворков становится намного проще.
Например, вы можете обновлять фронтенд с минимальными затратами и изменениями в бизнес-коде. Использование данных для драйверства представлений также поможет лучше подготовиться к будущим кастомным drag-and-drop формам.
Это также улучшит структуру хранения данных, делая её более понятной и удобной для поддержки. Указание: Пожалуйста, внимательно ознакомьтесь с комментариями в исходном коде, а также в представлении формы и представлении списка, сложные формы можно использовать в комбинации.## Пример
# Проверка
node -v
# Настройка китайского источника
npm config set registry https://registry.npmmirror.com
npm i -g pnpm
# Проверка
pnpm -v
# Настройка китайского источника
pnpm config set registry https://registry.npmmirror.com
git clone https://gitee.com/thinkgem/jeesite-vue.git
cd jeesite-vue
Внимание: Не размещайте в директориях с китайскими именами или с пробелами.- Установка зависимостей
pnpm install
pnpm dev
Среда разработки загружает большое количество файлов, что облегчает отладку. Пожалуйста, будьте терпеливы.
pnpm preview
После сборки, файлы будут объединены, поэтому производительность доступа будет значительно повышена. В среде производства можно включить gzip.
pnpm build
После сборки, в корневой директории будет создан каталог dist
, который можно разместить на nginx.
Дополнительная информация: https://jeesite.com/docs/vue-install-deploy/#развертывание-на-рабочем-сервере
# Настройка прокси, можно настроить несколько, без переноса строки, формат: [корневой путь доступа к интерфейсу, адрес прокси, сохранять ли заголовок Host]
# VITE_PROXY = [["/js","https://vue.jeesite.com/js",true]]
VITE_PROXY = [["/js","http://127.0.0.1:8980/js",false]]# Корневой путь для доступа к интерфейсу (например: https://vue.jeesite.com)
VITE_GLOB_API_URL =
# Префикс для доступа к интерфейсу, следующий за корневым путем
VITE_GLOB_API_URL_PREFIX = /js
// Определение событий страницы const emit = defineEmits(['success', 'register']);
// Метод интернационализации, параметр - корневой путь интернационализации const { t } = useI18n('test.testData');
// Метод отображения сообщений const { showMessage } = useMessage();
// Метаданные маршрута const { meta } = unref(router.currentRoute);
// Текущие данные страницы const record = ref({}); // Определение заголовка текущей страницы, определено в менеджере меню const getTitle = computed(() => ({ icon: meta.icon || 'ant-design:book-outlined', value: record.value.isNewRecord ? t('Добавить данные') : t('Редактировать данные'), })); </script>
const inputFormSchemas: FormSchema[] = [
{
label: t('Однострочное текстовое поле'), // Надпись перед элементом управления
field: 'testInput', // Имя поля для отправки данных формы
component: 'Input', // Тип элемента управления (может быть пользовательским, для более подробной информации см. componentMap.ts)
componentProps: { // Определение свойств компонента
maxlength: 200,
},
required: true, // Проверка формы, обязательное поле (быстрое определение)
rules: [ // Если требуется что-то больше, чем просто обязательное поле, можно определить через rules, пример:
{ required: true },
{ min: 4, max: 20, message: t('Введите текст длиной от 4 до 20 символов') },
{ pattern: /^[\u0391-\uFFE5\w]+$/, message: t('Не допускаются специальные символы') },
{
validator(_rule, value) {
return new Promise((resolve, reject) => {
if (!value || value === '') return resolve();
// Дистанционная проверка, проверка данных на повторение на сервере
checkTestInput(record.value.testInput || '', value)
.then((res) => (res ? resolve() : reject(t('Данные уже существуют'))))
.catch((err) => reject(err.message || t('Проверка не удалась')));
});
},
trigger: 'blur', // Если это дистанционная проверка, можно уменьшить частоту запросов
},
],
},
];
``` colProps: { lg: 24, md: 24 }, // Грид-расположение (соответствует стилю Ant Design)
},
{
label: t('Выпадающий список'),
field: 'testSelect',
component: 'Select', // Тип выпадающего списка (другие варианты: RadioGroup, CheckboxGroup)
componentProps: {
dictType: 'sys_menu_type', // Тип словаря для определения значений выпадающего списка
allowClear: true, // Разрешить очистку выбора
mode: 'multiple', // Режим выпадающего списка, разрешить множественный выбор
},
},
{
label: t('Выбор даты'),
field: 'testDate',
component: 'DatePicker',
componentProps: {
format: 'YYYY-MM-DD', // Формат выбора даты
showTime: false, // Отключить выбор времени
},
},
{
label: t('Выбор даты и времени'),
field: 'testDatetime',
component: 'DatePicker',
componentProps: {
format: 'YYYY-MM-DD HH:mm', // Формат выбора даты и времени
showTime: { format: 'HH:mm' }, // Установка формата времени
},
},
{
label: t('Выбор пользователя'),
field: 'testUser.userCode',
fieldLabel: 'testUser. userName', // Поддерживает возврат, например, для элементов выпадающего списка или дерева выбора
component: 'TreeSelect', // Компонент выбора дерева
componentProps: {
api: officeTreeData, // Определение API данных, поддерживающее формат ztree
params: { isLoadUser: true, userIdPrefix: '' }, // Параметры API
canSelectParent: false, // Разрешить выбор родительского элемента
allowClear: true,
},
},
{
label: t('дочерние данные таблицы'),
field: 'testDataChildList',
component: 'Input',
colProps: { lg: 24, md: 24 },
},```markdown
// Определение параметров текущей формы
const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
labelWidth: 120, // Ширина меток перед элементами управления
schemas: inputFormSchemas, // Список определений элементов управления
baseColProps: { lg: 12, md: 24 }, // Базовые параметры сетки элементов управления (адаптивный дизайн)
});
```// Определение подтаблицы текущей формы
const [registerTestDataChildTable, testDataChildTable] = useTable({
actionColumn: { // Определение колонки действий подтаблицы
width: 60, // Ширина колонки действий
actions: (record: Recordable) => [
{
icon: 'i-ant-design:delete-outlined',
color: 'error',
popConfirm: { // Включение диалогового окна подтверждения
title: 'Подтвердите удаление',
confirm: handleTestDataChildDelete.bind(this, record),
},
auth: 'sys:empUser:edit', // Права доступа кнопки (управление отображением кнопки)
},
],
},
rowKey: 'id', // Идентификатор строки подтаблицы
pagination: false,// Отключение пагинации
bordered: true, // Включение границ таблицы
size: 'small', // Размер ячеек (межстрочный интервал)
inset: true, // Включение встроенной таблицы (удаление некоторых отступов)
});// Автоматическое определение подтаблицы текущей формы
async function setTestDataChildTableData(_res: Recordable) {
testDataChildTable.setColumns([
{
title: t('Однострочный текст'),
dataIndex: 'testInput',
width: 230,
align: 'left',
editRow: true, // Включение редактирования
editComponent: 'Input', // Элемент управления редактирования (можно настроить, подробнее в componentMap.ts)
editRule: true, // Валидация элемента управления (необходимость заполнения)
},
{
title: t('Выпадающий список'),
dataIndex: 'testSelect',
width: 130,
align: 'left',
dictType: 'sys_menu_type', // Указание типа словаря, автоматическое отображение меток словаря
editRow: true,
editComponent: 'Select',
editComponentProps: { // Параметры элемента управления
dictType: 'sys_menu_type', // Тип поля выпадающего списка
allowClear: true,
},
editRule: false,
},
// Дополнительные определения элементов управления не приводятся, аналогично определению элементов управления формы...
]);
// Установка данных подтаблицы
testDataChildTable.setTableData(record.value.testDataChildList || []);
}
``` // При клике по строке, включаем редактирование
function handleTestDataChildRowClick(record: Recordable) {
record.onEdit?.(true, false);
}``` // Добавление строки для редактирования, можно указать начальные данные
function handleTestDataChildAdd() {
testDataChildTable.insertTableDataRecord({
id: new Date().getTime(),
isNewRecord: true,
editable: true,
});
}
// Метод удаления строки для редактирования
function handleTestDataChildDelete(record: Recordable) {
testDataChildTable.deleteTableDataRecord(record);
}
// Получение данных из дочерней таблицы (поддерживает возврат удаленных, но не подтвержденных данных)
async function getTestDataChildList() {
let testDataChildListValid = true;
let testDataChildList: Recordable[] = [];
for (const record of testDataChildTable.getDataSource()) {
// Валидация данных в контролах и отмена редактирования строки (если валидация не пройдена, возвращаем false)
if (!(await record.onEdit?.(false, true))) {
testDataChildListValid = false;
}
testDataChildList.push({
...record,
id: !!record.isNewRecord ? '' : record.id,
});
}
for (const record of testDataChildTable.getDelDataSource()) {
if (!!record.isNewRecord) continue;
testDataChildList.push({
...record,
status: '1',
});
}
// Валидация данных из дочерней таблицы, выбрасываем ошибку, если данные не прошли валидацию
if (!testDataChildListValid) {
throw { errorFields: [{ name: ['testDataChildList'] }] };
}
return testDataChildList;
} // Обработчик событий после открытия модального окна, выполняет инициализацию данных формы и т. д.
const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
resetFields(); // Сброс данных формы
setDrawerProps({ loading: true }); // Отображение загрузки
const res = await testDataForm(data); // Запрос данных формы
record.value = (res.testData || {}) as Recordable;
setFieldsValue(record.value); // Установка значений полей
setTestDataChildTableData(res); // Установка данных из дочерней таблицы (если нет дочерней таблицы, можно не указывать)
setDrawerProps({ loading: false }); // Скрытие загрузки
});```markdown
// Метод для отправки формы
async function handleSubmit() {
try {
const data = await validate(); // Валидация формы и возврат данных
setDrawerProps({ confirmLoading: true }); // Отображение загрузки подтверждения
// Установка параметров для отправки (QueryString, контроллер backend принимает get)
const params: any = {
isNewRecord: record.value.isNewRecord,
id: record.value.id,
};
// Получение и установка данных для дочерней таблицы
data.testDataChildList = await getTestDataChildList();
// console.log('submit', params, data, record);
// Отправка данных на сервер (если отправка не удалась, перейти к catch)
const res = await testDataSave(params, data);
showMessage(res.message); // Отображение результата отправки
setTimeout(closeDrawer); // Скрытие всплывающего окна
emit('success', data); // Вызов события для обновления данных в списке
} catch (error: any) {
if (error && error.errorFields) {
showMessage(t('Вы ввели неверную информацию, пожалуйста, исправьте её по подсказкам.'));
}
console.log('error', error);
}
} } finally {
setDrawerProps({ confirmLoading: false }); // Скрытие загрузки подтверждения
}
}
</script>
```### Список представлений``````html
<template>
<div>
<!-- Таблица компонент -->
<BasicTable @register="registerTable">
<!-- Заголовок таблицы слот -->
<template #tableTitle>
<Icon :icon="getTitle.icon" class="m-1 pr-1" />
<span> {{ getTitle.value }} </span>
</template>
<!-- Слот кнопок справа таблицы, где v-auth используется для контроля прав доступа -->
<template #toolbar>
<a-button type="primary" @click="handleForm({})" v-auth="'test:testData:edit'">
<Icon icon="i-fluent:add-12-filled" /> {{ t('Добавить') }}
</a-button>
</template>
<!-- Слот первой колонки -->
<template #firstColumn="{ record }">
<a @click="handleForm({ id: record.id })">
{{ record.testInput }}
</a>
</template>
</BasicTable>
<!-- Модальное окно формы ввода, открытое при щелчке по строке таблицы -->
<InputForm @register="registerDrawer" @success="handleSuccess" />
</div>
</template>
<!-- Имя скрипта: имя текущего компонента (соответствует имени маршрута, если не соответствует, кэширование страницы будет недействительным) -->
<script lang="ts" setup name="ViewsTestTestDataList">
// Импорт используемых объектов, часть опущена
import InputForm from './form.vue';
// Вызов метода интернационализации, параметр - это корневой путь кодировки интернационализации
const { t } = useI18n('test.testData');
// Метод уведомления о сообщении
const { showMessage } = useMessage();
// Метаданные маршрута
const { meta } = unref(router.currentRoute);
</script>
``` // Определение заголовка текущей страницы, определено в менеджере меню
const getTitle = {
icon: meta.icon || 'ant-design:book-outlined',
value: meta.title || t('Data Management'),
};
</script>
``````markdown
// Определение формы поиска для таблицы
const searchForm: FormProps = {
baseColProps: { lg: 6, md: 8 }, // Грид-расположение формы
labelWidth: 90, // Ширина меток формы
schemas: [
{
label: t('Однострочное текстовое поле'), // Метка формы
field: 'testInput', // Имя параметра для отправки формы
component: 'Input', // Тип компонента формы
},
{
label: t('Выпадающий список'),
field: 'testSelect',
component: 'Select', // Компонент выбора (также поддерживает RadioGroup, CheckboxGroup)
componentProps: {
dictType: 'sys_menu_type', // Тип словаря для определения значений выпадающего списка
allowClear: true, // Разрешить очистку значения
mode: 'multiple', // Режим выпадающего списка (множественный выбор)
},
},
// Дополнительные компоненты, которые не показаны здесь, аналогичны предыдущему разделу формы
],
};
``` // Определение столбцов таблицы
const tableColumns: BasicColumn[] = [
{
title: t('Однострочное текстовое поле'), // Заголовок столбца
dataIndex: 'testInput', // Имя свойства столбца
key: 'a.test_input', // Имя поля для сортировки
sorter: true, // Возможность сортировки по заголовку
width: 230, // Ширина столбца
align: 'left', // Выравнивание столбца
},
]; // Опциональные слоты для настройки внешнего вида или добавления элементов управления
slot: 'firstColumn',
},
{
title: t('Выпадающий список'),
dataIndex: 'testSelect',
key: 'a.test_select',
sorter: true,
width: 130,
align: 'center',
dictType: 'sys_menu_type', // Тип словаря для быстрого отображения меток
},
]; // Определение столбца действий таблицы
const actionColumn: BasicColumn = {
width: 160, // Ширина столбца действий
actions: (record: Recordable) => [
{
icon: 'i-clarity:note-edit-line',
title: t('Редактировать данные'),
onClick: handleForm.bind(this, { id: record.id }),
// Управление правами доступа, указание строки с правами
auth: 'test:testData:edit',
},
{
icon: 'i-ant-design:stop-outlined',
color: 'error',
title: t('Отключить данные'),
// Управление диалогом подтверждения
popConfirm: {
title: t('Подтвердите отключение данных'),
confirm: handleDisable.bind(this, { id: record.id }),
},
// Управление отображением кнопки
show: () => record.status === '0',
ifShow: () => record.status === '0',
// Управление правами доступа, указание строки с правами
auth: 'test:testData:edit',
},
],
// Опции для выпадающего списка действий
dropDownActions: (record: Recordable) => [
{
icon: 'i-ant-design:reload-outlined',
label: t('Сбросить пароль'),
onClick: handleResetpwd.bind(this, { userCode: record.userCode }),
auth: 'sys:empUser:resetpwd',
},
],
}; // Определение диалогового окна, вызываемого при нажатии на первый столбец или кнопку редактирования
const [registerDrawer, { openDrawer }] = useDrawer(); // Определение таблицы
const [registerTable, { reload }] = useTable({
api: testDataListData, // API для данных таблицы
beforeFetch: (params) => {
return params; // Изменение параметров перед отправкой API
},
columns: tableColumns, // Колонки таблицы
actionColumn: actionColumn, // Колонка действий
formConfig: searchForm, // Конфигурация формы поиска
showTableSetting: true, // Показывать ли кнопку настройки в правом верхнем углу
useSearchForm: true, // Использовать ли форму поиска
canResize: true, // Можно ли изменять размер таблицы
});## Условия лицензионного соглашения1. Распространяется на условиях лицензии Apache License Version 2.0 и может использоваться в коммерческих проектах, но необходимо соблюдать дополнительные условия.
2. Не следует применять данное программное обеспечение для действий, вредящих национальной безопасности, чести и интересам страны, а также не следует использовать его с целью нарушения закона.
3. При использовании данного программного обеспечения, которое интегрирует множество открытых источников, необходимо соблюдать условия лицензий этих открытых источников.
4. В расширенном коде (модифицированном и производном коде) необходимо включать оригинальные условия лицензии, авторские права и другие требования оригинальных авторов (уважайте авторские права, не удаляйте или не изменяйте информацию о авторстве в файлах, включая `Copyright` и `@author`).
5. Работы, основанные на данном программном обеспечении, могут использовать JeeSite5 в качестве сервера, за исключением случаев, когда коммерческое использование и распространение исходного кода запрещены.
6. Если вы используете некоторые части кода или функции из данного программного обеспечения, укажите источник в описании вашего программного обеспечения, например: "Программа разработана на основе JeeSite Vue быстрого разработчика" и добавьте ссылку: http://jeesite.com.
7.Любые юридические споры или ответственность, возникшие в результате использования данного программного обеспечения, не относятся к нашей компании.
8. Если вы улучшили данное программное обеспечение, мы будем рады принять ваш вклад и двигаться вперед вместе.
9. В этом проекте подана заявка на авторское право, поэтому уважайте открытый исходный код, спасибо за чтение.## Поддержка и обслуживание
* Данное программное обеспечение предоставляется бесплатно, но мы предлагаем соответствующие платные услуги, потому что:
* Без финансовой поддержки сложно развиваться, особенно для хорошего продукта. Если JeeSite помог вам, пожалуйста, поддержите нас. Взаимодействуя с нами, вы получите больше вознаграждений, мы будем делать больше для общественного блага, открывать больше ресурсов и возвращать их обществу. Пожалуйста, дайте нам немного мотивации, мы очень благодарны за поддержку наших друзей!
* **Свяжитесь с нами**: посетите страницу поддержки и обслуживания по адресу: <http://s.jeesite.com>
## Дополнительные функции в профессиональной версии
1. Свободный выбор из трех стилей для вкладок темы
2. Управление бизнес-процессами, проектирование и управление процессами
3. Управление файлами, быстрое загрузка файлов, предварительный просмотр файлов
4. Расширенные сворачиваемые формы и персонализированное локальное хранение
5. Персонализированное локальное хранение параметров настройки таблиц
6. Функции управления арендаторами, переключение арендаторов
7. Динамическое изменение размера шрифта страниц
8. Правый клик на вкладках, открытие в новом окне
9. Отправка уведомлений, напоминания
10. Многокультурная поддержка, локализация
11. Быстрое обновление до Monorepo скриптом
12. Дополнительные функции см. документацию
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )