3 Commits

Author SHA1 Message Date
zc
2143b8d77d 处理打印页面CSS强制换行 2026-06-02 21:01:06 +08:00
zc
237eabc298 去除默认账号密码,去除自动填充 2026-05-13 14:27:06 +08:00
zc
37b70fe25e 优化双数据源 2026-05-13 14:02:31 +08:00
10 changed files with 74 additions and 44 deletions

View File

@@ -8,6 +8,7 @@ export interface UserResp {
email: string email: string
phone: string phone: string
description: string description: string
dataSource: number
status: 1 | 2 status: 1 | 2
isSystem?: boolean isSystem?: boolean
createUserString: string createUserString: string

View File

@@ -15,7 +15,7 @@ export const systemRoutes: RouteRecordRaw[] = [
path: '/', path: '/',
name: 'Dashboard', name: 'Dashboard',
component: Layout, component: Layout,
redirect: '/dashboard/analysis', // 改为跳转到分析 redirect: '/workOrder', // 改为跳转到工作订单
meta: { title: '仪表盘', icon: 'dashboard', hidden: false }, meta: { title: '仪表盘', icon: 'dashboard', hidden: false },
children: [ children: [
{ {
@@ -25,9 +25,9 @@ export const systemRoutes: RouteRecordRaw[] = [
meta: { title: '工作台', icon: 'desktop', hidden: true }, // 改为隐藏 meta: { title: '工作台', icon: 'desktop', hidden: true }, // 改为隐藏
}, },
{ {
path: '/dashboard/analysis', path: '/workOrder',
name: 'Analysis', name: 'WorkOrder',
component: () => import('@/views/dashboard/analysis/index.vue'), component: () => import('@/views/workOrder/index.vue'),
meta: { title: '首页', icon: 'insert-chart', hidden: false, affix: true }, meta: { title: '首页', icon: 'insert-chart', hidden: false, affix: true },
}, },
], ],

View File

@@ -500,7 +500,7 @@ const printLabel = async () => {
.qr-cell { width: 24mm; text-align: center; vertical-align: middle; border: 1px solid #000; } .qr-cell { width: 24mm; text-align: center; vertical-align: middle; border: 1px solid #000; }
.label-row { display: flex; align-items: center; } .label-row { display: flex; align-items: center; }
.label-field { font-size: 8pt; font-weight: bold; margin-right: 2mm; min-width: 25pt; } .label-field { font-size: 8pt; font-weight: bold; margin-right: 2mm; min-width: 25pt; }
.label-value { font-size: 8pt; font-weight: bold; flex: 1; } .label-value { font-size: 8pt; font-weight: bold; flex: 1; word-break: break-all; }
.qr-code img { width: 20mm; height: 20mm; margin: 1mm 0; } .qr-code img { width: 20mm; height: 20mm; margin: 1mm 0; }
.mark-number { font-size: 8pt; font-weight: bold; margin-top: 1mm; text-align: center; } .mark-number { font-size: 8pt; font-weight: bold; margin-top: 1mm; text-align: center; }
.serial-number { font-size: 8pt; font-weight: bold; margin-top: 1mm; } .serial-number { font-size: 8pt; font-weight: bold; margin-top: 1mm; }
@@ -638,6 +638,7 @@ defineOptions({ name: 'print' })
font-size: 12px; font-size: 12px;
font-weight: bold; font-weight: bold;
flex: 1; flex: 1;
word-break: break-all;
} }
.qr-code img { .qr-code img {

View File

@@ -31,10 +31,10 @@
</a-button> </a-button>
</template> </template>
<template #toolbar-right> <template #toolbar-right>
<a-button v-permission="['fullWorkOrder:fullWorkOrder:add']" type="primary" @click="onAdd"> <!-- <a-button v-permission="['fullWorkOrder:fullWorkOrder:add']" type="primary" @click="onAdd">-->
<template #icon><icon-plus /></template> <!-- <template #icon><icon-plus /></template>-->
<template #default>新增</template> <!-- <template #default>新增</template>-->
</a-button> <!-- </a-button>-->
<a-button v-permission="['fullWorkOrder:fullWorkOrder:export']" @click="onExport"> <a-button v-permission="['fullWorkOrder:fullWorkOrder:export']" @click="onExport">
<template #icon><icon-download /></template> <template #icon><icon-download /></template>
<template #default>导出</template> <template #default>导出</template>
@@ -50,11 +50,11 @@
<template #action="{ record }"> <template #action="{ record }">
<a-space> <a-space>
<a-link <!-- <a-link-->
@click="onAddDetail(record.id)" <!-- @click="onAddDetail(record.id)"-->
> <!-- >-->
新增 <!-- 新增-->
</a-link> <!-- </a-link>-->
<a-link <a-link
@click="onViewDetail(record)" @click="onViewDetail(record)"
> >
@@ -78,22 +78,21 @@
</template> </template>
</GiTable> </GiTable>
<FullWorkOrderAddModal ref="FullWorkOrderAddModalRef" @save-success="search" /> <!-- <FullWorkOrderAddModal ref="FullWorkOrderAddModalRef" @save-success="search" />-->
<FullWorkOrderDetailModal ref="FullWorkOrderDetailModalRef" @save-success="search" /> <!-- <FullWorkOrderDetailModal ref="FullWorkOrderDetailModalRef" @save-success="search" />-->
<FullWorkOrderDetailListModal ref="FullWorkOrderDetailListModalRef" /> <FullWorkOrderDetailListModal ref="FullWorkOrderDetailListModalRef" />
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import FullWorkOrderAddModal from './FullWorkOrderAddModal.vue' // import FullWorkOrderAddModal from './FullWorkOrderAddModal.vue'
import FullWorkOrderDetailModal from './FullWorkOrderDetailModal.vue' // import FullWorkOrderDetailModal from './FullWorkOrderDetailModal.vue'
import FullWorkOrderDetailListModal from './FullWorkOrderDetailListModal.vue' import FullWorkOrderDetailListModal from './FullWorkOrderDetailListModal.vue'
import { type FullWorkOrderResp, type FullWorkOrderQuery, deleteFullWorkOrder, exportFullWorkOrder, listFullWorkOrder } from '@/apis/fullWorkOrder/fullWorkOrder' import { type FullWorkOrderResp, type FullWorkOrderQuery, deleteFullWorkOrder, exportFullWorkOrder, listFullWorkOrder } from '@/apis/fullWorkOrder/fullWorkOrder'
import type { TableInstanceColumns } from '@/components/GiTable/type' import type { TableInstanceColumns } from '@/components/GiTable/type'
import { useDownload, useTable } from '@/hooks' import { useDownload, useTable } from '@/hooks'
import { isMobile } from '@/utils' import { isMobile } from '@/utils'
import has from '@/utils/has' import has from '@/utils/has'
import type {WorkOrderResp} from "@/apis/workOrder/workOrder";
import QRCode from 'qrcode'; import QRCode from 'qrcode';
import {Message} from "@arco-design/web-vue"; import {Message} from "@arco-design/web-vue";
@@ -226,7 +225,7 @@ const onPrint = async (record: FullWorkOrderResp) => {
.qr-cell { width: 24mm; text-align: center; vertical-align: middle; border: 1px solid #000; } .qr-cell { width: 24mm; text-align: center; vertical-align: middle; border: 1px solid #000; }
.label-row { display: flex; align-items: center; } .label-row { display: flex; align-items: center; }
.label-field { font-size: 8pt; font-weight: bold; margin-right: 2mm; min-width: 25pt; } .label-field { font-size: 8pt; font-weight: bold; margin-right: 2mm; min-width: 25pt; }
.label-value { font-size: 8pt; font-weight: bold; flex: 1; } .label-value { font-size: 8pt; font-weight: bold; flex: 1; word-break: break-all; }
.qr-code img { width: 20mm; height: 20mm; margin: 1mm 0; } .qr-code img { width: 20mm; height: 20mm; margin: 1mm 0; }
.mark-number { font-size: 8pt; font-weight: bold; margin-top: 1mm; text-align: center; } .mark-number { font-size: 8pt; font-weight: bold; margin-top: 1mm; text-align: center; }
.serial-number { font-size: 8pt; font-weight: bold; margin-top: 1mm; } .serial-number { font-size: 8pt; font-weight: bold; margin-top: 1mm; }
@@ -326,19 +325,19 @@ const onExport = () => {
useDownload(() => exportFullWorkOrder(queryForm)) useDownload(() => exportFullWorkOrder(queryForm))
} }
const FullWorkOrderAddModalRef = ref<InstanceType<typeof FullWorkOrderAddModal>>() // const FullWorkOrderAddModalRef = ref<InstanceType<typeof FullWorkOrderAddModal>>()
const FullWorkOrderDetailModalRef = ref<InstanceType<typeof FullWorkOrderDetailModal>>() // const FullWorkOrderDetailModalRef = ref<InstanceType<typeof FullWorkOrderDetailModal>>()
const FullWorkOrderDetailListModalRef = ref<InstanceType<typeof FullWorkOrderDetailListModal>>() const FullWorkOrderDetailListModalRef = ref<InstanceType<typeof FullWorkOrderDetailListModal>>()
// 新增 // 新增
const onAdd = () => { // const onAdd = () => {
FullWorkOrderAddModalRef.value?.onAdd() // FullWorkOrderAddModalRef.value?.onAdd()
} // }
// 新增原材料详情 // 新增原材料详情
const onAddDetail = (id: string) => { // const onAddDetail = (id: string) => {
FullWorkOrderDetailModalRef.value?.onAdd(id) // FullWorkOrderDetailModalRef.value?.onAdd(id)
} // }
// 查看原材料详情 // 查看原材料详情
const onViewDetail = (record: FullWorkOrderResp) => { const onViewDetail = (record: FullWorkOrderResp) => {

View File

@@ -9,10 +9,10 @@
@submit="handleLogin" @submit="handleLogin"
> >
<a-form-item field="username" hide-label> <a-form-item field="username" hide-label>
<a-input v-model="form.username" placeholder="请输入用户名" allow-clear /> <a-input v-model="form.username" placeholder="请输入用户名" allow-clear autocomplete="off" />
</a-form-item> </a-form-item>
<a-form-item field="password" hide-label> <a-form-item field="password" hide-label>
<a-input-password v-model="form.password" placeholder="请输入密码" /> <a-input-password v-model="form.password" placeholder="请输入密码" autocomplete="new-password" />
</a-form-item> </a-form-item>
<a-form-item v-if="isCaptchaEnabled" field="captcha" hide-label> <a-form-item v-if="isCaptchaEnabled" field="captcha" hide-label>
<a-input v-model="form.captcha" placeholder="请输入验证码" :max-length="4" allow-clear style="flex: 1 1" /> <a-input v-model="form.captcha" placeholder="请输入验证码" :max-length="4" allow-clear style="flex: 1 1" />
@@ -41,15 +41,16 @@
import { type FormInstance, Message } from '@arco-design/web-vue' import { type FormInstance, Message } from '@arco-design/web-vue'
import { useStorage } from '@vueuse/core' import { useStorage } from '@vueuse/core'
import { getImageCaptcha } from '@/apis/common' import { getImageCaptcha } from '@/apis/common'
import { useTabsStore, useUserStore } from '@/stores' import { useAppStore, useTabsStore, useUserStore } from '@/stores'
import { encryptByRsa } from '@/utils/encrypt' import { encryptByRsa } from '@/utils/encrypt'
const loginConfig = useStorage('login-config', { const loginConfig = useStorage('login-config', {
rememberMe: true, // rememberMe: true,
username: 'admin', // 演示默认值 // username: 'admin', // 演示默认值
password: 'admin123', // 演示默认值 // password: 'admin123', // 演示默认值
// username: debug ? 'admin' : '', // 演示默认值 rememberMe: false,
// password: debug ? 'admin123' : '', // 演示默认值 username: '',
password: '',
}) })
// 是否启用验证码 // 是否启用验证码
const isCaptchaEnabled = ref(true) const isCaptchaEnabled = ref(true)
@@ -106,6 +107,7 @@ const getCaptcha = () => {
const userStore = useUserStore() const userStore = useUserStore()
const tabsStore = useTabsStore() const tabsStore = useTabsStore()
const appStore = useAppStore()
const router = useRouter() const router = useRouter()
const loading = ref(false) const loading = ref(false)
// 登录 // 登录
@@ -120,6 +122,8 @@ const handleLogin = async () => {
captcha: form.captcha, captcha: form.captcha,
uuid: form.uuid, uuid: form.uuid,
}) })
// 登录成功后获取系统配置(根据登录账号显示不同的系统名称)
await appStore.initSiteConfig()
tabsStore.reset() tabsStore.reset()
const { redirect, ...othersQuery } = router.currentRoute.value.query const { redirect, ...othersQuery } = router.currentRoute.value.query
const { rememberMe } = loginConfig.value const { rememberMe } = loginConfig.value

View File

@@ -23,7 +23,7 @@
import { ref, reactive, onMounted, onUnmounted } from 'vue' import { ref, reactive, onMounted, onUnmounted } from 'vue'
import { type FormInstance, Message } from '@arco-design/web-vue' import { type FormInstance, Message } from '@arco-design/web-vue'
import { useRouter } from 'vue-router' import { useRouter } from 'vue-router'
import { useTabsStore, useUserStore } from '@/stores' import { useAppStore, useTabsStore, useUserStore } from '@/stores'
const formRef = ref<FormInstance>() const formRef = ref<FormInstance>()
const form = reactive({ const form = reactive({
@@ -38,6 +38,7 @@ const rules: FormInstance['rules'] = {
const userStore = useUserStore() const userStore = useUserStore()
const tabsStore = useTabsStore() const tabsStore = useTabsStore()
const appStore = useAppStore()
const router = useRouter() const router = useRouter()
const loading = ref(false) const loading = ref(false)
@@ -58,6 +59,9 @@ const handleLogin = async () => {
// 调用后端接口校验卡号 // 调用后端接口校验卡号
await userStore.cardLogin(form) await userStore.cardLogin(form)
// 登录成功后获取系统配置(根据登录账号显示不同的系统名称)
await appStore.initSiteConfig()
// 登录成功后移除事件监听器 // 登录成功后移除事件监听器
if (keyDownListener) { if (keyDownListener) {
document.removeEventListener('keydown', keyDownListener) document.removeEventListener('keydown', keyDownListener)

View File

@@ -19,9 +19,9 @@
<a-tab-pane key="1" title="账号登录"> <a-tab-pane key="1" title="账号登录">
<component :is="AccountLogin" v-if="activeTab === '1'" /> <component :is="AccountLogin" v-if="activeTab === '1'" />
</a-tab-pane> </a-tab-pane>
<a-tab-pane key="2" title="刷卡"> <!-- <a-tab-pane key="2" title="刷卡">-->
<component :is="CardLogin" v-if="activeTab === '2'" /> <!-- <component :is="CardLogin" v-if="activeTab === '2'" />-->
</a-tab-pane> <!-- </a-tab-pane>-->
</a-tabs> </a-tabs>
</div> </div>
</a-col> </a-col>
@@ -51,7 +51,8 @@ defineOptions({ name: 'Login' })
const { isDesktop } = useDevice() const { isDesktop } = useDevice()
const appStore = useAppStore() const appStore = useAppStore()
const title = computed(() => appStore.getTitle()) // 登录页面显示固定的"称重系统"
const title = '称重系统'
const logo = computed(() => appStore.getLogo()) const logo = computed(() => appStore.getLogo())
const isEmailLogin = ref(false) const isEmailLogin = ref(false)

View File

@@ -20,7 +20,7 @@ import { type ColumnItem, GiForm } from '@/components/GiForm'
import type { Gender, Status } from '@/types/global' import type { Gender, Status } from '@/types/global'
import { GenderList } from '@/constant/common' import { GenderList } from '@/constant/common'
import { useResetReactive } from '@/hooks' import { useResetReactive } from '@/hooks'
import { useDept, useRole } from '@/hooks/app' import {useDept, useDict, useRole} from '@/hooks/app'
import { encryptByRsa } from '@/utils/encrypt' import { encryptByRsa } from '@/utils/encrypt'
const emit = defineEmits<{ const emit = defineEmits<{
@@ -28,6 +28,7 @@ const emit = defineEmits<{
}>() }>()
const { width } = useWindowSize() const { width } = useWindowSize()
const { data_source } = useDict('data_source')
const dataId = ref('') const dataId = ref('')
const visible = ref(false) const visible = ref(false)
@@ -102,6 +103,17 @@ const columns: ColumnItem[] = reactive([
allowSearch: true, allowSearch: true,
}, },
}, },
{
label: '系统数据源',
field: 'dataSource',
type: 'select',
span: 24,
required: true,
props: {
options: data_source,
allowClear: true,
},
},
{ {
label: '描述', label: '描述',
field: 'description', field: 'description',

View File

@@ -55,6 +55,9 @@
<a-tag v-if="record.isSystem" color="red" size="small"></a-tag> <a-tag v-if="record.isSystem" color="red" size="small"></a-tag>
<a-tag v-else color="arcoblue" size="small"></a-tag> <a-tag v-else color="arcoblue" size="small"></a-tag>
</template> </template>
<template #dataSource="{ record }">
<GiCellTag :value="record.dataSource" :dict="data_source" />
</template>
<template #action="{ record }"> <template #action="{ record }">
<a-space> <a-space>
<a-link v-permission="['system:user:update']" title="修改" @click="onUpdate(record)">修改</a-link> <a-link v-permission="['system:user:update']" title="修改" @click="onUpdate(record)">修改</a-link>
@@ -103,9 +106,12 @@ import { useDownload, useResetReactive, useTable } from '@/hooks'
import { isMobile } from '@/utils' import { isMobile } from '@/utils'
import has from '@/utils/has' import has from '@/utils/has'
import type {ColumnItem} from "@/components/GiForm"; import type {ColumnItem} from "@/components/GiForm";
import {useDict} from "@/hooks/app";
defineOptions({ name: 'SystemUser' }) defineOptions({ name: 'SystemUser' })
const { data_source } = useDict('data_source')
// 查询表单 // 查询表单
const [queryForm, resetForm] = useResetReactive({ const [queryForm, resetForm] = useResetReactive({
description: undefined, description: undefined,
@@ -173,6 +179,7 @@ const columns: TableInstanceColumns[] = [
{ title: '性别', dataIndex: 'gender', slotName: 'gender', align: 'center' }, { title: '性别', dataIndex: 'gender', slotName: 'gender', align: 'center' },
{ title: '角色', dataIndex: 'roleNames', slotName: 'roleNames', minWidth: 165 }, { title: '角色', dataIndex: 'roleNames', slotName: 'roleNames', minWidth: 165 },
{ title: '手机号', dataIndex: 'phone', minWidth: 170, ellipsis: true, tooltip: true }, { title: '手机号', dataIndex: 'phone', minWidth: 170, ellipsis: true, tooltip: true },
{ title: '系统数据源', dataIndex: 'dataSource', slotName: 'dataSource',minWidth: 170, ellipsis: true, tooltip: true },
{ title: '系统内置', dataIndex: 'isSystem', slotName: 'isSystem', width: 100, align: 'center', show: false }, { title: '系统内置', dataIndex: 'isSystem', slotName: 'isSystem', width: 100, align: 'center', show: false },
{ title: '描述', dataIndex: 'description', minWidth: 130, ellipsis: true, tooltip: true }, { title: '描述', dataIndex: 'description', minWidth: 130, ellipsis: true, tooltip: true },
{ title: '创建人', dataIndex: 'createUserString', width: 140, ellipsis: true, tooltip: true, show: false }, { title: '创建人', dataIndex: 'createUserString', width: 140, ellipsis: true, tooltip: true, show: false },

View File

@@ -485,7 +485,7 @@ const printLabel = async () => {
.qr-cell { width: 24mm; text-align: center; vertical-align: middle; border: 1px solid #000; } .qr-cell { width: 24mm; text-align: center; vertical-align: middle; border: 1px solid #000; }
.label-row { display: flex; align-items: center; } .label-row { display: flex; align-items: center; }
.label-field { font-size: 8pt; font-weight: bold; margin-right: 2mm; min-width: 25pt; } .label-field { font-size: 8pt; font-weight: bold; margin-right: 2mm; min-width: 25pt; }
.label-value { font-size: 8pt; font-weight: bold; flex: 1; } .label-value { font-size: 8pt; font-weight: bold; flex: 1; word-break: break-all; }
.qr-code img { width: 20mm; height: 20mm; margin: 1mm 0; } .qr-code img { width: 20mm; height: 20mm; margin: 1mm 0; }
.mark-number { font-size: 8pt; font-weight: bold; margin-top: 1mm; text-align: center; } .mark-number { font-size: 8pt; font-weight: bold; margin-top: 1mm; text-align: center; }
.serial-number { font-size: 8pt; font-weight: bold; margin-top: 1mm; } .serial-number { font-size: 8pt; font-weight: bold; margin-top: 1mm; }
@@ -644,6 +644,7 @@ defineOptions({ name: 'LabelPrint' })
font-size: 10pt; font-size: 10pt;
flex: 1; flex: 1;
font-weight: bold; font-weight: bold;
word-break: break-all;
} }
.qr-code img { .qr-code img {