果酱 发布的文章

Sql:

WITH tmp AS ( SELECT cardnum, MAX ( receivetime ) AS receivetime FROM uwb20230626 GROUP BY cardnum ) 
SELECT b.*, A.farfromroadway, A.backroadwaydirection 
FROM
worksite    A 
INNER JOIN uwb20230626 b ON A.NO = b.sitenum
INNER JOIN tmp ON b.receivetime = tmp.receivetime AND b.cardnum = tmp.cardnum

FreeSql

用ToSql模拟With...AS(...)

var sql = db.Fsql.Select<UwbLoc>()
    .AsTable((t, old) => t == typeof(UwbLoc) ? tablename : old)
    .FromQuery(db.Fsql.Select<UwbLoc>()
         .AsTable((t, old) => tablename)
         .GroupBy(a => a.cardnum)
         .WithTempQuery(g => new
         {
              cardnum = g.Key,
              receivetime = g.Max(g.Value.receivetime)
         })
     )
    .Where((a, b) => a.cardnum == b.cardnum && a.receivetime == b.receivetime)
    .WithTempQuery((a,b) => a)  //此处必须要wisthtempQuery,不能直接在tosql((a,b) => a),因为tosql会将列结果加 as as1,使下面withsql列名不一致
    .ToSql();

var data = await db.Fsql.Select<UwbLoc, WorkSite>()
    .WithSql(sql, null)         //sql里已经有astable处理,这不用再添加astable,否则会重复,变成union select联合查询
    .InnerJoin((x, y) => x.sitenum == y.No && y.isdel == false)
    .Where((x, y) => x.distance > y.FarFromRoadWay && y.BackRoadWayDirection != 0 && x.direction == 2 / y.BackRoadWayDirection)
    .ToListAsync((x, y) => new WorkSiteCfgDto
    {
        Distance = x.distance,
        No = y.No,
        Name = y.Name,
        FarFromRoadWay = y.FarFromRoadWay,
    });

注意

  • AsTable会通过WithSql传入查询中,所以不需要再次AsTable,否则多次AsTable会变成Union Select
  • ToSql(x => {...}) 会在sql中自动添加列命名cardnum as as1,导致列名不一致报列不存在错误,须WithTempQuery生成子查询结果

基本思路

用系统函数SHGetFileInfo获得文件信息,如图标、大小、更新日期等,放入TreeView控件

SHGetFileInfo如下:

/// <summary> 返回系统设置的图标 </summary>  
/// <param name="pszPath">文件路径 如果为""  返回文件夹的</param>  
/// <param name="dwFileAttributes">0</param>  
/// <param name="psfi">结构体</param>  
/// <param name="cbSizeFileInfo">结构体大小</param>  
/// <param name="uFlags">枚举类型</param>  
/// <returns>-1失败</returns>  
[DllImport("shell32.dll")]
public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);
public System.Drawing.Icon GetSystemInfoIcon(string path)
{
    SHFILEINFO _SHFILEINFO = new SHFILEINFO();
    IntPtr _IconIntPtr = SHGetFileInfo(path, 0, ref _SHFILEINFO, (uint)Marshal.SizeOf(_SHFILEINFO), (uint)(SHGFI.SHGFI_ICON | SHGFI.SHGFI_LARGEICON));
    if (_IconIntPtr.Equals(IntPtr.Zero)) return null;
    System.Drawing.Icon _Icon = System.Drawing.Icon.FromHandle(_SHFILEINFO.hIcon);
    return _Icon;
}

刷新内容

CurrentPath变化触发PropertyChangedCallback

完整代码

HeBianGu.Control.Explorer
File-Explorer


背景

  • Windows 平台
  • -jar 发布

问题一:windows文件互传

同网络已经有一台windows上搭好的Jenkins环境(78),和目标发布机不是同一台主机(178)。尝试从78的jenkins上用脚本把发布包传到178,可用的方法是FTP、NFS、SMB等,没有linux下scp/ssh等,非常不方便,有类似的winscp/openssh需要再安装配置。最终放弃了还是在178再部署一个jenkins服务。

jenkins admin默认密码在".jenkins\secrets\initialAdminPassword"

问题二:maven配置私有nexus库

  1. pom.yam
<project>
    <repositories>
        <!-- 配置nexus远程仓库 -->
        <repository>
            <id>nexus-releases</id>
            <name>Nexus Snapshot Repository</name>
            <url>http://192.168.8.106:8081/repository/maven-public/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>
    <!-- 配置从哪个仓库中下载构件,即jar包 -->
    <pluginRepositories>
        <pluginRepository>
            <id>nexus-releases</id>
            <name>Nexus Releases Repository</name>
            <url>http://192.168.8.106:8081/repository/maven-public/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>
</project>
  1. maven settings.xml添加权限认证
<servers>
    <server>
      <id>nexus-releases</id>
      <username>admin</username>
      <password>admin1234</password>
    </server>
      <server>
      <id>nexus-snapshots</id>
      <username>admin</username>
      <password>admin1234</password>
    </server>
  </servers>
注意:pom里repository的\<id>必须和settings中server里的\<id>一致

问题三:Jenkins Bat 脚本

上代码,Jenkins 脚本

:: 备份设置BUILD_ID 号,防止Jenkins杀进程
set OLD_BUILD_ID=%BUILD_ID%
echo %OLD_BUILD_ID%
set BUILD_ID=DONTKILLME
cmd /c "C:\ProgramData\Jenkins\.jenkins\workspace\TV-Sensor-Backend\deploy.cmd"
set BUILD_ID=%OLD_BUILD_ID%
echo %BUILD_ID%

178上的发布脚本deploy.cmd

call:killtask 
call:compile && call:backup && call:copyfile && call:run

exit

:compile
D:\apache-maven-3.9.1\bin\mvn -Dmaven.test.skip=true clean package && echo 编译成功
goto:eof

:killtask
taskkill /IM "backendjavaw.exe" /F && echo 结束进程
goto:eof

:backup
E: && cd E:\Yiritech\yiritech-backend && del iotUimc-0.0.7-SNAPSHOT.jar.bak & rename iotUimc-0.0.7-SNAPSHOT.jar iotUimc-0.0.7-SNAPSHOT.jar.bak && echo 备份成功
goto:eof

:copyfile
copy "C:\ProgramData\Jenkins\.jenkins\workspace\TV-Sensor-Backend\target\iotUimc-0.0.7-SNAPSHOT.jar" "E:\Yiritech\yiritech-backend\iotUimc-0.0.7-SNAPSHOT.jar" && echo 拷贝成功
goto:eof

:: 把javaw重命名为backendjavaw
:run
start E:\Yiritech\jdk-11.0.2\bin\backendjavaw.exe -Xms500M -Xmx500M -XX:MaxDirectMemorySize=64M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=E:\Yiritech\yiritech-backend\iotUimcLog\backendOomDump.hprof -XX:+PrintGCDetails -jar iotUimc-0.0.7-SNAPSHOT.jar --spring.config.location=application.yml  && echo 更新成功
goto:eof

问题四:Jenkins CRSF 安全限制

因为高版本Jenkins默认开启了CSRF(Cross-site request forgery)跨站请求伪造,导至Git推送报错。Jenkins设置没有关闭选项,需添加 Java 启动参数:

-Dhudson.security.csrf.GlobalCrumbIssuerConfiguration.DISABLE_CSRF_PROTECTION=true

问题五:yarn install 报错:The lockfile would have been modified by this install

Jenkins(CI)会改变yarn.lock,需要给矛权限,添加--no-immutable表明不锁定yarn.lock

yarn install --no-immutable
或
set YARN_ENABLE_IMMUTABLE_INSTALLS=false 
yarn install

问题六:指定 git 分支,Jenkins的 %BRANCH_NAME% 不能用

前端的打包脚本会检查git分支名,否则会失败,因此需要 git switch 指定分支
由于Jenkins的 %BRANCH_NAME% 不可用,改用 Git Parameter 插件在This project is parameterized配置变量
前端脚本

:: %BRANCH_NAME%是空值
echo %BRANCH_NAME%
echo %branch%
git checkout -f %branch%
:: origin/release/WZSYS.1A.4.0,跳过origin字符
git switch %branch:~7%
echo 开始编译
:: node版本兼容
SET NODE_OPTIONS=--openssl-legacy-provider 
set YARN_ENABLE_IMMUTABLE_INSTALLS=false
rmdir /s /q "C:\ProgramData\Jenkins\.jenkins\workspace\WenZhen-Vue\dist" & "C:\Program Files\nodejs\yarn" install && "C:\Program Files\nodejs\yarn" run build && echo 编译成功 

要点

  1. AMD的Path,内核补丁
  2. 无线网卡

    AirportItlwm.kext
    Recovery模式时,只有BigSur及以下版本能找到网络
  3. 进Recovery卡EB代码,必须开启Securebootmodel,安装完进系统又不用开
  4. 在Recovery,联网不久就会卡住,画面动不了

    boot-arg:增加 debug=0x100,防止内核错误重启(不确定)
    This disables macOS's watchdog which helps prevents a reboot on a kernel panic
  5. RX580 2048SP这张卡是阉割卡,MacOS不能免驱,表现是能点亮但是不找不到显卡

    需要刷显卡Bios,刷成RX570就能免驱
    工具限制需要在windows下才能刷,教程:黑苹果教程之RX580 2048sp刷vbios降为RX570
    注意:amdvbflash.exe工具要用老版本,新版本限制不让刷了
  6. 睡眼无法唤醒,键盘电源都断了

    HibernationFixup.kext修复睡死
    20231005更新:上面设置了还是睡死,发现是BOIS问题。刷入最新微星BOIS,打开唤醒设置->USB唤醒。

2026/6/2更新

  1. Recovery镜像必须下指定版本,在https://github.com/acidanthera/OpenCorePkg/blob/master/Utilities/macrecovery/recovery_urls.txt指定的,官方文档里的会报错。

    ./macrecovery.py -b Mac-2BD1B31983FE1663 -m 00000000000000000 download
  2. 升级到Ventura13.7.8,成功了,但是wifi用不了,有线网可以。
    解决办法:把AirportItlwm.kext升级到ventura版本,然后重建下缓存/System/Library/Caches/,可以用Hackintool->工具->重建缓存并修复权限(在下面一排的图标),最后重启
  3. 无法登录icloud
    解决:设置网卡pcid,built-in=01,参考 关于黑苹果登陆icloud时无法联系服务器或者登录Apple ID提示连接Apple ID服务器时出错
  4. OC引导Windows会丢失激活
隐藏黑苹果的 SMBIOS (仿冒硬件信息)Windows 被取消激活,通常是因为 OC 把苹果的序列号和机型(SMBIOS)传给了 Windows。
解决:1.导航到 Kernel (内核设置) -> Quirks,勾选 CustomSMBIOSGuid 为 True (开启)。2.导航到 PlatformInfo (机型信息),将 UpdateSMBIOSMode 设置为 Custom。

问题

  • 显卡hdmi输出,显示器声音没有 在系统设置中心里选择声音输出

成品仓库


关键类 SpeechSynthesizer

using System.Speech.Synthesis;

filePath = Path.Combine(filePath, $"{fileName}.wav");
//string filePath = _hostingEnvironment.ContentRootPath + $"\\wwwroot\\speech\\{fileName}.wav";
if (System.IO.File.Exists(filePath))
{
   return  Json(new { code = 0, msg = "语音存在了!", url = $"/speech/{fileName}.wav" });
}
else
{
  using (SpeechSynthesizer synth = new SpeechSynthesizer())
  {
     synth.SetOutputToWaveFile(filePath, new SpeechAudioFormatInfo(32000, AudioBitsPerSample.Sixteen, AudioChannel.Mono));
     PromptBuilder builder = new PromptBuilder();
     builder.AppendText(text);
     synth.Speak(builder);
  }
  return  Json(new { code = 2, msg = "生成语音成功!", url = $"/speech/{fileName}.wav" });
}

System.Speech.Synthesis 命名空间