template.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. <template>
  2. <a-row :gutter="[8, 8]" >
  3. <a-col :span="4" >
  4. <a-card title="分组" style="height: 100%;" >
  5. <template #extra >
  6. <a-button type="primary" @click="state.groupVisible = true" >添加分组</a-button>
  7. </template>
  8. <a-tree
  9. v-model:expandedKeys="expandedKeys"
  10. v-model:selectedKeys="state.treeActiveKey"
  11. :tree-data="state.groupList"
  12. defaultExpandAll
  13. autoExpandParent
  14. :field-names="{
  15. key: 'id',
  16. title: 'groupName',
  17. }"
  18. >
  19. <template #title="record">
  20. <a-space @click="changeTreeActiveKey(record.key)" >
  21. <div class="group-label" > {{ record.groupName }} </div>
  22. <template v-if="state.treeActiveKey[0] === record.id && record.id" >
  23. <plus-circle-outlined @click="openGroupModal('add', record)"/>
  24. <!-- <delete-outlined @click="openGroupModal('del', record)"/> -->
  25. </template>
  26. </a-space>
  27. </template>
  28. </a-tree>
  29. </a-card>
  30. </a-col>
  31. <a-col :span="20">
  32. <a-card
  33. :tab-list="tabList"
  34. style="height: 100%;"
  35. :active-tab-key="tabKey"
  36. @tabChange="onChangeTab"
  37. >
  38. <table-pro
  39. :service="serviceMap!.service"
  40. :serviceParams="{[serviceMap!.paramsKey!.name]: searchName}"
  41. :columns="serviceMap?.columns"
  42. @add="openModal"
  43. ref="tableProDom"
  44. >
  45. <template #search >
  46. <a-space>
  47. <input-tsx v-model:value="searchName" :placeholder="serviceMap!.placeholder" />
  48. <a-button type="primary" @click="search" >搜索</a-button>
  49. </a-space>
  50. </template>
  51. <template #render="{column, record}" >
  52. <template v-if="column.key === 'sex'" >
  53. <a-tag :color="record.sex === 0 ? 'pink' : record.sex === 1 ? 'blue' : 'grey'" >{{record.sex === 0 ? '女' : record.sex === 1 ? '男' : '其他'}}</a-tag>
  54. </template>
  55. <template v-if="column.key === 'carUrl'" > <a-image :width="86" :src="record.carUrl"/> </template>
  56. <template v-if="column.key === 'faceUrl'" > <a-image :width="86" :src="record.faceUrl"/> </template>
  57. <template v-if="column.key === 'frockUrl'" > <a-image :width="86" :src="record.frockUrl"/> </template>
  58. <template v-if="column.key === 'action'" >
  59. <a @click="delData(record)" >删除</a>
  60. </template>
  61. </template>
  62. </table-pro>
  63. </a-card>
  64. </a-col>
  65. </a-row>
  66. <modal-pro
  67. width="700px"
  68. :title="serviceMap?.title"
  69. :open="state.visible"
  70. @cancel="closeModal"
  71. @ok="submit"
  72. >
  73. <a-form style="width: 100%;" :labelCol="{span: 3}" :wrapperCol="{span: 14}" >
  74. <a-form-item label="名称" v-bind="validateInfos.name" >
  75. <InputTsx allowClear placeholder="请输入名称" v-model:value="formState.name" />
  76. </a-form-item>
  77. <a-form-item label="性别" v-if="tabKey === 'face'" >
  78. <a-radio-group v-model:value="formState.sex" button-style="solid">
  79. <a-radio-button :value="0">女</a-radio-button>
  80. <a-radio-button :value="1">男</a-radio-button>
  81. <a-radio-button :value="2">其他</a-radio-button>
  82. </a-radio-group>
  83. </a-form-item>
  84. <a-form-item label="图片" v-bind="validateInfos.url">
  85. <UploadPro action="/cvs/file/upload" accept=".png,.jpg,.jpeg" @done="uploadDone" />
  86. </a-form-item>
  87. </a-form>
  88. </modal-pro>
  89. <modal-pro
  90. width="700px"
  91. title='创建分组'
  92. :open="state.groupVisible"
  93. @cancel="state.groupVisible = false"
  94. @ok="addGroup"
  95. >
  96. <a-form style="width: 100%;" :labelCol="{span: 3}" :wrapperCol="{span: 14}" >
  97. <a-form-item label="群组名称" v-bind="groupValidateInfos.groupName" >
  98. <InputTsx allowClear placeholder="请输入设备名称" v-model:value="groupState.groupName" />
  99. </a-form-item>
  100. </a-form>
  101. </modal-pro>
  102. </template>
  103. <script lang='ts' setup >
  104. import { FeatureController } from '@/controller'
  105. import { computed, nextTick, onMounted, reactive, ref, toRef, toRefs } from 'vue'
  106. import { InputTsx } from '@/components/MicroComponents'
  107. import { Form } from 'ant-design-vue'
  108. import UploadPro from '@/components/UploadPro/index'
  109. import { PlusCircleOutlined } from '@ant-design/icons-vue'
  110. const tabList = [{ key: 'car', tab: '车辆库' }, { key: 'face', tab: '人脸库' }, { key: 'frock', tab: '工装库' }]
  111. const tabKey = ref('car')
  112. const carColumns = [
  113. {
  114. title: '车辆ID',
  115. dataIndex: 'id',
  116. key: 'id'
  117. },
  118. {
  119. title: '车牌号',
  120. dataIndex: 'carNo',
  121. key: 'carNo'
  122. },
  123. {
  124. title: '车辆图片',
  125. dataIndex: 'carUrl',
  126. key: 'carUrl'
  127. },
  128. {
  129. title: '操作',
  130. dataIndex: 'action',
  131. key: 'action'
  132. }
  133. ]
  134. const faceColumns = [
  135. {
  136. title: '人脸ID',
  137. dataIndex: 'id',
  138. key: 'id'
  139. },
  140. {
  141. title: '人脸名称',
  142. dataIndex: 'faceName',
  143. key: 'faceName'
  144. },
  145. {
  146. title: '性别',
  147. dataIndex: 'sex',
  148. key: 'sex'
  149. },
  150. {
  151. title: '人脸图片',
  152. dataIndex: 'faceUrl',
  153. key: 'faceUrl'
  154. },
  155. {
  156. title: '操作',
  157. dataIndex: 'action',
  158. key: 'action'
  159. }
  160. ]
  161. const frockColumns = [
  162. {
  163. title: '工装ID',
  164. dataIndex: 'id',
  165. key: 'id'
  166. },
  167. {
  168. title: '工装名称',
  169. dataIndex: 'faceName',
  170. key: 'faceName'
  171. },
  172. {
  173. title: '工装图片',
  174. dataIndex: 'frockUrl',
  175. key: 'frockUrl'
  176. },
  177. {
  178. title: '操作',
  179. dataIndex: 'action',
  180. key: 'action'
  181. }
  182. ]
  183. const useForm = Form.useForm
  184. const searchName = ref('')
  185. const tableProDom = ref()
  186. const state = reactive<{
  187. visible: boolean,
  188. groupVisible: boolean,
  189. groupList: CVS.Feature.Group[]
  190. treeActiveKey: number[]
  191. }>({
  192. visible: false,
  193. groupVisible: false,
  194. groupList: [],
  195. treeActiveKey: [0]
  196. })
  197. const expandedKeys = ref<string[]>([])
  198. const groupState = reactive({
  199. groupName: '',
  200. upGroupId: 0,
  201. key: ''
  202. })
  203. const dataMap = new Map([
  204. ['car', { placeholder: '请输入车牌号', service: FeatureController.carPage, paramsKey: { name: 'carNo', url: 'carUrl' }, columns: carColumns, title: '创建车辆', post: FeatureController.addCar, del: FeatureController.delCarById }],
  205. ['face', { placeholder: '请输入人脸名称', service: FeatureController.facePage, paramsKey: { name: 'faceName', url: 'faceUrl' }, columns: faceColumns, title: '创建人脸', post: FeatureController.addFace, del: FeatureController.delFaceById }],
  206. ['frock', { placeholder: '请输入工装名称', service: FeatureController.frockPage, paramsKey: { name: 'frockName', url: 'frockUrl' }, columns: frockColumns, title: '创建工装', post: FeatureController.addFrock, del: FeatureController.delFrockById }]
  207. ])
  208. const serviceMap = computed(() => dataMap.get(tabKey.value))
  209. const formState = reactive({
  210. sex: 0,
  211. name: '',
  212. url: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F26a3b3c9-1833-4385-a294-8d4f12afacd6%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1704166834&t=dbe51dba1f1fb8c6536e6dfa5337b0e7'
  213. })
  214. const { resetFields, validate, validateInfos } = useForm(formState, {
  215. name: [{ required: true, message: '请填写' }],
  216. url: [{ required: true, message: '请上传' }]
  217. })
  218. const { resetFields: groupResetFields, validate: groupValidate, validateInfos: groupValidateInfos } = useForm(groupState, {
  219. groupName: [{ required: true, message: '请填写群组名称' }]
  220. })
  221. const delData = async (record) => {
  222. await serviceMap.value?.del(record.id)
  223. tableProDom.value.reload()
  224. }
  225. const onChangeTab = (key) => {
  226. tabKey.value = key
  227. nextTick(() => {
  228. tableProDom.value.reload({ page: 0 })
  229. })
  230. }
  231. const changeTreeActiveKey = (id: string, e?: TouchEvent) => {
  232. e && e.stopPropagation && e.stopPropagation()
  233. state.treeActiveKey[0] = id
  234. console.log(state.treeActiveKey)
  235. getGroupList()
  236. tableProDom.value.reload({ page: 0 })
  237. // state.groupList = state.groupList.find(item => item.upGroupId === state.treeActiveKey)
  238. }
  239. const uploadDone = (url: string) => {
  240. console.log(url)
  241. }
  242. const submit = () => {
  243. validate().then(async () => {
  244. await serviceMap.value?.post({
  245. ...{
  246. [serviceMap.value.paramsKey.name]: formState.name,
  247. [serviceMap.value.paramsKey.url]: formState.url,
  248. sex: formState.sex
  249. },
  250. groupId: state.treeActiveKey[0]
  251. })
  252. closeModal()
  253. tableProDom.value.reload()
  254. }).catch(() => {})
  255. }
  256. const openModal = () => {
  257. resetFields({})
  258. state.visible = true
  259. }
  260. const closeModal = () => state.visible = false
  261. const search = () => tableProDom.value.reload()
  262. const addGroup = () => {
  263. groupValidate().then(async () => {
  264. await FeatureController.addGroup(groupState)
  265. state.groupVisible = false
  266. getGroupList()
  267. }).catch(() => {})
  268. }
  269. interface TreeNode {
  270. id: string;
  271. createAt: number;
  272. updateAt: number | null;
  273. deleted: boolean;
  274. groupName: string;
  275. upGroupId: string;
  276. tenantId: string;
  277. children?: TreeNode[];
  278. }
  279. function buildTree (data: TreeNode[], upGroupId: string): TreeNode[] {
  280. const tree: TreeNode[] = []
  281. for (const node of data) {
  282. if (node.upGroupId === upGroupId) {
  283. const children = buildTree(data, node.id)
  284. if (children.length) {
  285. node.children = children
  286. }
  287. tree.push({
  288. ...node,
  289. key: node.id,
  290. hasChildren: !!node.children?.length
  291. })
  292. }
  293. }
  294. return tree
  295. }
  296. const openGroupModal = (type: 'add', record) => {
  297. console.log('record:', record)
  298. groupState.groupName = ''
  299. groupState.upGroupId = ''
  300. state.groupVisible = true
  301. groupState.upGroupId = record.upGroupId
  302. }
  303. const getGroupList = async () => {
  304. const data = await FeatureController.groupList()
  305. state.groupList = [
  306. {
  307. groupName: '所有分组',
  308. key: '',
  309. id: '',
  310. children: buildTree(data, 0)
  311. }
  312. ]
  313. expandedKeys.value = state.groupList[0].children.map(item => item.id)
  314. console.log('expandedKeys.value[0].id:', expandedKeys.value[0])
  315. state.treeActiveKey[0] = expandedKeys.value[0]
  316. }
  317. onMounted(() => {
  318. getGroupList()
  319. })
  320. </script>
  321. <style lang='less' scoped >
  322. </style>