master
lzq 2025-12-20 11:49:02 +08:00
parent a9ab89a4fc
commit 2426d96fc5
12 changed files with 343 additions and 133 deletions

View File

@ -1,13 +1,19 @@
import type { Plugin } from 'vite' import type { Plugin } from 'vite'
import fs from 'fs' import fs from 'fs'
/**
*
* @param options
*/
export function fileWatcher(...options: VitePluginTypes.FileWatcherOptions[]): Plugin { export function fileWatcher(...options: VitePluginTypes.FileWatcherOptions[]): Plugin {
console.log(`启动文件监听器,处理器数量:${options == null ? 0 : options.length}`)
return { return {
name: 'file-watcher-plugin', name: 'file-watcher-plugin',
configureServer(server) { configureServer(server) {
server.watcher server.watcher
.on('all', (event, filePath, stats) => { .on('all', (event, filePath, stats) => {
if (options == null || options.length === 0) return
options.forEach(it => { options.forEach(it => {
const isDir = stats!.isDirectory() const isDir = stats!.isDirectory()
const getContent = () => { const getContent = () => {

View File

@ -1,7 +1,8 @@
import fs from 'fs' import fs from 'fs'
import path from 'node:path' import path from 'node:path'
interface IconfontJson { /*
interface IconfontJson {
font_family: string; font_family: string;
css_prefix_text: string; css_prefix_text: string;
glyphs: { glyphs: {
@ -10,35 +11,35 @@ interface IconfontJson {
unicode: string unicode: string
name: string name: string
}[]; }[];
} }
*/
const targetFile = path.resolve(__dirname, './public/iconfont/ali/iconfont.json') const targetFile = path.resolve(__dirname, '../src/components/a-icon/iconfont.json')
const outPath = path.resolve(__dirname, './src/components/iconfont') const outPath = path.resolve(__dirname, '../src/components/a-icon')
/**
*
*/
export default { export default {
process(data: VitePluginTypes.FileWatcherProcessParam) { process(data: VitePluginTypes.FileWatcherProcessParam) {
const text = data.getContent()
const json = JSON.parse(data.getContent()) as IconfontJson const tsFile = path.resolve(outPath, 'iconfont.ts')
const names = json.glyphs.map(glyph => glyph.font_class)
const dtsFile = outPath + '/iconfont.d.ts'
console.log('正在生成文件:', dtsFile)
const dts = `export {}
declare global {
namespace IconfontTypes {
type name = ${names.map(name => `'${name}'`).join('\n | ')}
}
}
`
fs.writeFileSync(dtsFile, dts, {encoding: 'utf-8'})
const tsFile = outPath + '/icons.ts'
const ts = `export default reactive([${'\n ' + names.map(name => `{name: '${name}'}`).join(',\n ') + '\n'}])`
console.log('正在生成文件:', tsFile) console.log('正在生成文件:', tsFile)
fs.writeFileSync(tsFile, ts, {encoding: 'utf-8'}) const tsContent = `export const icons = ${text.trim()} as const
console.log('文件生成完成') export type IconName = (typeof icons.glyphs)[number]['font_class']
export interface IconGlyphs {
icon_id: string
name: string
font_class: IconName
unicode: string
unicode_decimal: number
}
`
fs.writeFileSync(tsFile, tsContent, {encoding: 'utf-8'})
}, },
isAccept(data: VitePluginTypes.FileWatcherAcceptParam) { isAccept(data: VitePluginTypes.FileWatcherAcceptParam) {
return data.event === 'change' && !data.isDir && data.filePath === targetFile return data.event === 'change' && !data.isDir && data.filePath === targetFile

32
plugin/types.d.ts vendored
View File

@ -2,23 +2,55 @@ export {}
declare global { declare global {
namespace VitePluginTypes { namespace VitePluginTypes {
/**
*
*/
type FileWatcherEvent = 'add' | 'addDir' | 'change' | 'unlink' | 'unlinkDir' type FileWatcherEvent = 'add' | 'addDir' | 'change' | 'unlink' | 'unlinkDir'
interface FileWatcherProcessParam { interface FileWatcherProcessParam {
/**
*
*/
event: FileWatcherEvent event: FileWatcherEvent
/**
*
*/
filePath: string filePath: string
/**
*
*/
isDir: boolean isDir: boolean
/**
*
*/
getContent: () => string getContent: () => string
} }
interface FileWatcherAcceptParam { interface FileWatcherAcceptParam {
/**
*
*/
event: FileWatcherEvent event: FileWatcherEvent
/**
*
*/
filePath: string filePath: string
/**
*
*/
isDir: boolean isDir: boolean
} }
interface FileWatcherOptions { interface FileWatcherOptions {
/**
*
* @param data
*/
process: (data: FileWatcherProcessParam) => void process: (data: FileWatcherProcessParam) => void
/**
*
* @param data
*/
isAccept: (data: FileWatcherAcceptParam) => boolean isAccept: (data: FileWatcherAcceptParam) => boolean
} }
} }

View File

@ -1,30 +0,0 @@
import '@/components/a-icon/iconfont.css'
import {
type IconName,
icons,
} from '@/components/a-icon/iconfont.ts'
import {
computed,
defineComponent,
} from 'vue'
export default defineComponent(
(props, {attrs}) => {
const prefixText = icons.css_prefix_text
const fontFamily = icons.font_family
const icon = computed(() => {
return props.name == null ? [] : [ fontFamily, prefixText + props.name ]
})
return () => (<><i class={icon.value} {...attrs}></i></>)
},
{
props: {
name: {
type: String as PropType<IconName>,
required: false,
validator: (_: string) => true,
},
},
name: 'AIcon',
})

View File

@ -0,0 +1,25 @@
<script lang="ts" setup>
import {
type IconName,
icons,
} from '@/components/a-icon/iconfont.ts'
import '@/components/a-icon/iconfont.css'
const props = defineProps<{
name?: IconName
}>()
const prefixText = icons.css_prefix_text
const fontFamily = icons.font_family
const icon = computed(() => {
console.log(props.name, 2222)
return props.name == null ? [] : [ fontFamily, prefixText + props.name ]
})
</script>
<template>
<i :class="icon" v-bind="$attrs"/>
</template>
<style lang="stylus" scoped>
</style>

View File

@ -0,0 +1,170 @@
{
"id": "4985351",
"name": "再昇云",
"font_family": "iconfont",
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "8582929",
"name": "编辑/修改",
"font_class": "bianji",
"unicode": "e604",
"unicode_decimal": 58884
},
{
"icon_id": "41408341",
"name": "扣款",
"font_class": "koukuanliebiao",
"unicode": "e63b",
"unicode_decimal": 58939
},
{
"icon_id": "33376724",
"name": "余额充值",
"font_class": "yuechongzhi",
"unicode": "e8f5",
"unicode_decimal": 59637
},
{
"icon_id": "6949389",
"name": "删除订单;报表;清单",
"font_class": "shanchudingdan-mian",
"unicode": "e6d7",
"unicode_decimal": 59095
},
{
"icon_id": "16695459",
"name": "取消订单",
"font_class": "quxiaodingdan",
"unicode": "e64a",
"unicode_decimal": 58954
},
{
"icon_id": "14443392",
"name": "历史轨迹-蓝",
"font_class": "lishiguiji-lan",
"unicode": "e672",
"unicode_decimal": 58994
},
{
"icon_id": "44180887",
"name": "过磅单据",
"font_class": "guobangdanju",
"unicode": "e66c",
"unicode_decimal": 58988
},
{
"icon_id": "26397534",
"name": "电子小票",
"font_class": "dianzixiaopiao",
"unicode": "e64d",
"unicode_decimal": 58957
},
{
"icon_id": "12814001",
"name": "详情",
"font_class": "xiangqing",
"unicode": "e611",
"unicode_decimal": 58897
},
{
"icon_id": "9777840",
"name": "关联单据",
"font_class": "guanliandanju",
"unicode": "e61d",
"unicode_decimal": 58909
},
{
"icon_id": "28095045",
"name": "准运证",
"font_class": "track",
"unicode": "e603",
"unicode_decimal": 58883
},
{
"icon_id": "18446165",
"name": "关联单选",
"font_class": "guanliandanxuan",
"unicode": "e68f",
"unicode_decimal": 59023
},
{
"icon_id": "8725687",
"name": "订单详情",
"font_class": "dingdanxiangqing",
"unicode": "e6bf",
"unicode_decimal": 59071
},
{
"icon_id": "23500943",
"name": "通知",
"font_class": "tongzhi",
"unicode": "e86a",
"unicode_decimal": 59498
},
{
"icon_id": "27250248",
"name": "预警管理",
"font_class": "yujingguanli",
"unicode": "e61b",
"unicode_decimal": 58907
},
{
"icon_id": "25301786",
"name": "字典管理",
"font_class": "shujuguanli",
"unicode": "e70c",
"unicode_decimal": 59148
},
{
"icon_id": "3590945",
"name": "角色管理",
"font_class": "jiaoseguanli",
"unicode": "e62f",
"unicode_decimal": 58927
},
{
"icon_id": "20853364",
"name": "用户管理",
"font_class": "yingyongyonghuguanli",
"unicode": "e6aa",
"unicode_decimal": 59050
},
{
"icon_id": "25007161",
"name": "品类管理",
"font_class": "shangpinguanli",
"unicode": "fcf3",
"unicode_decimal": 64755
},
{
"icon_id": "9206620",
"name": "系统管理",
"font_class": "xitongguanli",
"unicode": "e85c",
"unicode_decimal": 59484
},
{
"icon_id": "20136570",
"name": "菜单管理",
"font_class": "pinleiguanli",
"unicode": "e63d",
"unicode_decimal": 58941
},
{
"icon_id": "15689628",
"name": "公司审核",
"font_class": "qiyezhuce",
"unicode": "e6a1",
"unicode_decimal": 59041
},
{
"icon_id": "5468041",
"name": "审核管理",
"font_class": "shenheguanli",
"unicode": "e639",
"unicode_decimal": 58937
}
]
}

View File

@ -165,8 +165,8 @@ export const icons = {
'font_class': 'shenheguanli', 'font_class': 'shenheguanli',
'unicode': 'e639', 'unicode': 'e639',
'unicode_decimal': 58937, 'unicode_decimal': 58937,
}, }
], ]
} as const } as const
export type IconName = (typeof icons.glyphs)[number]['font_class'] export type IconName = (typeof icons.glyphs)[number]['font_class']

View File

@ -8,7 +8,7 @@ import {
type MenuItemRegistered, type MenuItemRegistered,
} from 'element-plus' } from 'element-plus'
import { elIcons } from '@/common/element/element.ts' import { elIcons } from '@/common/element/element.ts'
import AIcon from '@/components/a-icon/AIcon.tsx' import AIcon from '@/components/a-icon/AIcon.vue'
import type { IconName } from '@/components/a-icon/iconfont.ts' import type { IconName } from '@/components/a-icon/iconfont.ts'
import styles from '@/pages/a-frame/aaside.module.styl' import styles from '@/pages/a-frame/aaside.module.styl'

View File

@ -9,17 +9,16 @@
</ElFormItem> --> </ElFormItem> -->
<ElFormItem label="身份类型"> <ElFormItem label="身份类型">
<el-select style="width: 200px" v-model="searchForm.identityCategory" placeholder="身份类型"> <el-select style="width: 200px" v-model="searchForm.identityCategory" placeholder="身份类型">
<el-option v-for="item in bizList" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in bizList" :key="item.value" :label="item.label" :value="item.value"/>
</el-select> </el-select>
</ElFormItem> </ElFormItem>
<!-- <ElFormItem label="客户姓名"> <!-- <ElFormItem label="客户姓名">
<ElInput v-model="searchForm.customerName" placeholder="客户姓名" /> <ElInput v-model="searchForm.customerName" placeholder="客户姓名" />
</ElFormItem> --> </ElFormItem> -->
<ElFormItem label="结算方式"> <ElFormItem label="结算方式">
<el-select v-model="searchForm.settlementWay" placeholder="结算方式" style="width: 200px"> <el-select v-model="searchForm.settlementWay" placeholder="结算方式" style="width: 200px">
<el-option v-for="item in payList" :key="item.value" :label="item.label" :value="item.value" /> <el-option v-for="item in payList" :key="item.value" :label="item.label" :value="item.value"/>
</el-select> </el-select>
</ElFormItem> </ElFormItem>
<!-- <!--
@ -49,25 +48,25 @@
<div class="tool-bar"> <div class="tool-bar">
<!-- <ElButton :icon="elIcons.Plus" type="primary" @click="addHandler"></ElButton> --> <!-- <ElButton :icon="elIcons.Plus" type="primary" @click="addHandler"></ElButton> -->
<ElButton :icon="elIcons.Filter" type="default" @click="showSearchForm = !showSearchForm" /> <ElButton :icon="elIcons.Filter" type="default" @click="showSearchForm = !showSearchForm"/>
</div> </div>
<ElTable v-loading="searching" :data="tableData" cell-class-name="table-cell" class="table-list" empty-text="暂无数据" header-row-class-name="table-header" row-key="id"> <ElTable v-loading="searching" :data="tableData" cell-class-name="table-cell" class="table-list" empty-text="暂无数据" header-row-class-name="table-header" row-key="id">
<!-- <ElTableColumn label="Id" prop="id" /> --> <!-- <ElTableColumn label="Id" prop="id" /> -->
<ElTableColumn label="账号" prop="username" /> <ElTableColumn label="账号" prop="username"/>
<ElTableColumn label="联系人" prop="nickname" /> <ElTableColumn label="联系人" prop="nickname"/>
<ElTableColumn label="身份类型" prop="identityCategoryTxt" /> <ElTableColumn label="身份类型" prop="identityCategoryTxt"/>
<ElTableColumn label="组织信息" prop="orgId" /> <ElTableColumn label="组织信息" prop="orgId"/>
<ElTableColumn label="客户姓名" prop="customerName" /> <ElTableColumn label="客户姓名" prop="customerName"/>
<!-- <ElTableColumn label="客户联系电话" prop="phone" /> --> <!-- <ElTableColumn label="客户联系电话" prop="phone" /> -->
<ElTableColumn label="结算方式" prop="settlementWayTxt" /> <ElTableColumn label="结算方式" prop="settlementWayTxt"/>
<ElTableColumn label="是否管理员"> <ElTableColumn label="是否管理员">
<template #default="scope"> <template #default="scope">
{{ scope.row.manager ? "是" : "否" }} {{ scope.row.manager ? '是' : '否' }}
</template> </template>
</ElTableColumn> </ElTableColumn>
<ElTableColumn label="联系电话" prop="phone" /> <ElTableColumn label="联系电话" prop="phone"/>
<ElTableColumn label="创建时间" prop="regdate" /> <ElTableColumn label="创建时间" prop="regdate"/>
<!-- <ElTableColumn label="修改时间" prop="modifyTime" /> --> <!-- <ElTableColumn label="修改时间" prop="modifyTime" /> -->
<!-- <ElTableColumn label="是否删除" prop="deleted"/> --> <!-- <ElTableColumn label="是否删除" prop="deleted"/> -->
<ElTableColumn label="操作" width="180"> <ElTableColumn label="操作" width="180">
@ -83,8 +82,8 @@
</template> </template>
</ElTableColumn> </ElTableColumn>
</ElTable> </ElTable>
<ElPagination class="pagination" layout="prev, pager, next" :page-size="pagination.size" :total="pagination.total" @change="pageChangeHandler" /> <ElPagination :page-size="pagination.size" :total="pagination.total" class="pagination" layout="prev, pager, next" @change="pageChangeHandler"/>
<CustomerForm ref="customerForm" @edit-succ="paging" /> <CustomerForm ref="customerForm" @edit-succ="paging"/>
</Page> </Page>
</template> </template>
@ -94,42 +93,45 @@ import CustomerForm from '@/pages/cst/customer/CustomerForm.vue'
import Page from '@/components/page/Page.vue' import Page from '@/components/page/Page.vue'
import { elIcons } from '@/common/element/element.ts' import { elIcons } from '@/common/element/element.ts'
const tableData = ref<CustomerTypes.SearchCustomerResult[]>([]); const tableData = ref<CustomerTypes.SearchCustomerResult[]>([])
let searchForm = reactive<CustomerTypes.SearchCustomerParam>({ let searchForm = reactive<CustomerTypes.SearchCustomerParam>({
current: 1, current: 1,
size: 20, size: 20,
}); })
const searching = ref(false); const searching = ref(false)
const deling = ref(false); const deling = ref(false)
const showSearchForm = ref(true); const showSearchForm = ref(true)
const customerFormIns = useTemplateRef<InstanceType<typeof CustomerForm>>("customerForm"); const customerFormIns = useTemplateRef<InstanceType<typeof CustomerForm>>('customerForm')
const pagination = reactive<G.Pagination>({ const pagination = reactive<G.Pagination>({
total: 0, total: 0,
current: 1, current: 1,
size: 1, size: 1,
}); })
function pageChangeHandler(currentPage: number, pageSize: number) { function pageChangeHandler(currentPage: number, pageSize: number) {
searchForm.current = currentPage; searchForm.current = currentPage
searchForm.size = pageSize; searchForm.size = pageSize
paging(); paging()
}
function showDialog(data?: CustomerTypes.SearchCustomerResult) {
customerFormIns.value?.open(data);
}
function delHandler({ row }: { row: CustomerTypes.SearchCustomerResult }) {
deling.value = true;
CustomerApi.del([row.id!])
.then(() => {
ElMessage.success("删除成功");
paging();
})
.finally(() => {
deling.value = false;
});
} }
function modifyHandler({ row }: { row: CustomerTypes.SearchCustomerResult }) { function showDialog(data?: CustomerTypes.SearchCustomerResult) {
showDialog(row); customerFormIns.value?.open(data)
}
function delHandler({row}: { row: CustomerTypes.SearchCustomerResult }) {
deling.value = true
CustomerApi.del([ row.id! ])
.then(() => {
ElMessage.success('删除成功')
paging()
})
.finally(() => {
deling.value = false
})
}
function modifyHandler({row}: { row: CustomerTypes.SearchCustomerResult }) {
showDialog(row)
} }
function reset() { function reset() {
@ -137,62 +139,62 @@ function reset() {
searchForm = reactive<CustomerTypes.SearchCustomerParam>({ searchForm = reactive<CustomerTypes.SearchCustomerParam>({
current: 1, current: 1,
size: 20, size: 20,
}); })
paging(); paging()
} }
function paging() { function paging() {
searching.value = true; searching.value = true
CustomerApi.paging(searchForm) CustomerApi.paging(searchForm)
.then((res) => { .then((res) => {
tableData.value = res.data?.records ?? []; tableData.value = res.data?.records ?? []
}) })
.finally(() => { .finally(() => {
searching.value = false; searching.value = false
}); })
} }
const payList = [ const payList = [
{ {
value: "YueJie", value: 'YueJie',
label: "月结", label: '月结',
}, },
{ {
value: "YuE", value: 'YuE',
label: "余额", label: '余额',
}, },
{ {
value: "XianFu", value: 'XianFu',
label: "现付", label: '现付',
}, },
]; ]
const bizList = [ const bizList = [
{ {
value: "ChanFei", value: 'ChanFei',
label: "产废方", label: '产废方',
}, },
{ {
value: "YunShu", value: 'YunShu',
label: "运输方", label: '运输方',
}, },
{ {
value: "XiaoNa", value: 'XiaoNa',
label: "消纳方", label: '消纳方',
}, },
{ {
value: "CaiGou", value: 'CaiGou',
label: "采购方", label: '采购方',
}, },
{ {
value: "SiJi", value: 'SiJi',
label: "司机", label: '司机',
}, },
]; ]
onMounted(() => { onMounted(() => {
paging(); paging()
}); })
</script> </script>
<style lang="stylus" scoped> <style lang="stylus" scoped>
@ -230,6 +232,7 @@ onMounted(() => {
:deep(.table-cell) { :deep(.table-cell) {
color #2F3540 color #2F3540
} }
.action-btn { .action-btn {
width 100% width 100%
display flex display flex

View File

@ -90,7 +90,7 @@ import {
type IconGlyphs, type IconGlyphs,
icons, icons,
} from '@/components/a-icon/iconfont.ts' } from '@/components/a-icon/iconfont.ts'
import AIcon from '@/components/a-icon/AIcon.tsx' import AIcon from '@/components/a-icon/AIcon.vue'
import ClientUtil from '@/common/utils/client-util.ts' import ClientUtil from '@/common/utils/client-util.ts'
import Utils from '@/common/utils' import Utils from '@/common/utils'

View File

@ -90,7 +90,7 @@ import { onMounted } from 'vue'
import { elIcons } from '@/common/element/element.ts' import { elIcons } from '@/common/element/element.ts'
import MenuForm from '@/pages/sys/menus/MenuForm.vue' import MenuForm from '@/pages/sys/menus/MenuForm.vue'
import Strings from '@/common/utils/strings.ts' import Strings from '@/common/utils/strings.ts'
import AIcon from '@/components/a-icon/AIcon.tsx' import AIcon from '@/components/a-icon/AIcon.vue'
import type { TableInstance } from 'element-plus' import type { TableInstance } from 'element-plus'
const tableData = ref<MenuTypes.SysMenu[]>([]) const tableData = ref<MenuTypes.SysMenu[]>([])

View File

@ -13,6 +13,8 @@ import zipDist from './plugin/zip-dist.ts'
import path from 'node:path' import path from 'node:path'
import ElementPlus from 'unplugin-element-plus/vite' import ElementPlus from 'unplugin-element-plus/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers' import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import { fileWatcher } from './plugin/file-watcher.ts'
import IconfontProcess from './plugin/iconfont-process.ts'
// https://vite.dev/config/ // https://vite.dev/config/
export default defineConfig((configEnv) => { export default defineConfig((configEnv) => {
@ -47,6 +49,7 @@ export default defineConfig((configEnv) => {
resolvers: [ ElementPlusResolver() ], resolvers: [ ElementPlusResolver() ],
}), }),
processHtml(env.VITE_APP_NAME), processHtml(env.VITE_APP_NAME),
fileWatcher(IconfontProcess),
zipDist(), zipDist(),
], ],
resolve: { resolve: {